├── .github └── FUNDING.yml ├── .gitignore ├── CMake └── curlcppConfig.cmake.in ├── CMakeLists.txt ├── CMakeScripts └── JoinPaths.cmake ├── LICENSE ├── README.md ├── include ├── cookie.h ├── cookie_date.h ├── cookie_datetime.h ├── cookie_time.h ├── curl_config.h ├── curl_cookie.h ├── curl_easy.h ├── curl_easy_info.h ├── curl_exception.h ├── curl_form.h ├── curl_global.h ├── curl_header.h ├── curl_info.h ├── curl_interface.h ├── curl_ios.h ├── curl_multi.h ├── curl_option.h ├── curl_pair.h ├── curl_receiver.h ├── curl_sender.h ├── curl_share.h └── curl_utility.h ├── src ├── CMakeLists.txt ├── cookie.cpp ├── cookie_date.cpp ├── cookie_datetime.cpp ├── cookie_time.cpp ├── curl_cookie.cpp ├── curl_easy.cpp ├── curl_exception.cpp ├── curl_form.cpp ├── curl_global.cpp ├── curl_header.cpp ├── curl_info.cpp ├── curl_multi.cpp ├── curl_share.cpp └── curlcpp.pc.in └── test ├── CMakeLists.txt ├── cookie.cpp ├── custom_request.cpp ├── easy.cpp ├── easy_info.cpp ├── header.cpp ├── multi.cpp ├── output_variable.cpp └── recv_header.cpp /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: https://www.bitcoinqrcodemaker.com/pay/?type=2&style=bitcoin&color=1&border=4&address=bc1qej7q0wuh3f944v9yx3s7a2ltn8aj6wyrddyc62 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | build/ 3 | blocks/ 4 | bii/build 5 | bii/cmake 6 | bii/deps 7 | bii/lib 8 | bii/.hive.db 9 | build.log 10 | .idea/ 11 | cmake-build-debug/ 12 | cmake-build-debug-visual-studio/ 13 | .vscode 14 | install 15 | .DS_Store 16 | *.out 17 | *.swp 18 | -------------------------------------------------------------------------------- /CMake/curlcppConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # curlcppConfig.cmake - Configuration file for external projects. 2 | @PACKAGE_INIT@ 3 | include(CMakeFindDependencyMacro) 4 | find_dependency(CURL CONFIG REQUIRED) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/curlcppTargets.cmake") 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10...3.15) 2 | 3 | # Setting up project 4 | project(curlcpp 5 | VERSION 3.1 6 | DESCRIPTION "An object oriented C++ wrapper for CURL (libcurl)" 7 | HOMEPAGE_URL "https://github.com/JosephP91/curlcpp/" 8 | LANGUAGES CXX) 9 | 10 | # For the pkg-config file. Please read https://github.com/jtojnar/cmake-snips 11 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMakeScripts") 12 | include(JoinPaths) 13 | 14 | include(GNUInstallDirs) 15 | 16 | option(BUILD_TEST "Build Tests" OFF) 17 | 18 | # if using an older VERSION of curl ocsp stapling can be disabled 19 | set(CURL_MIN_VERSION "7.34.0") 20 | 21 | set(DEFAULT_BUILD_TYPE "Release") 22 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 23 | message(STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.") 24 | set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE) 25 | # Set the possible values of build type for cmake-gui 26 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") 27 | endif() 28 | 29 | include(CheckIPOSupported) 30 | check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT ERROR) 31 | 32 | if(IPO_SUPPORTED) 33 | message(STATUS "IPO / LTO supported, will enable for targets in release build type") 34 | else() 35 | message(STATUS "IPO / LTO not supported: <${ERROR}>, will not enable") 36 | endif() 37 | 38 | option(CURLCPP_USE_PKGCONFIG "Use pkg-config to find libcurl. When off, find_package() will be used" OFF) 39 | 40 | # Set up source directories 41 | add_subdirectory(src) 42 | 43 | # Set up test directory. 44 | if(BUILD_TEST) 45 | add_subdirectory(test) 46 | endif() 47 | 48 | # Install 49 | install(EXPORT curlcppTargets NAMESPACE curlcpp:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/curlcpp) 50 | include(CMakePackageConfigHelpers) 51 | configure_package_config_file(CMake/curlcppConfig.cmake.in "${PROJECT_BINARY_DIR}/curlcppConfig.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/curlcpp") 52 | install(FILES ${PROJECT_BINARY_DIR}/curlcppConfig.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/curlcpp) 53 | 54 | join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}") 55 | join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") 56 | configure_file("${PROJECT_SOURCE_DIR}/src/curlcpp.pc.in" "${PROJECT_BINARY_DIR}/src/curlcpp.pc" @ONLY) 57 | install(FILES "${PROJECT_BINARY_DIR}/src/curlcpp.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") 58 | -------------------------------------------------------------------------------- /CMakeScripts/JoinPaths.cmake: -------------------------------------------------------------------------------- 1 | # This module provides function for joining paths 2 | # known from most languages 3 | # 4 | # SPDX-License-Identifier: (MIT OR CC0-1.0) 5 | # Copyright 2020 Jan Tojnar 6 | # https://github.com/jtojnar/cmake-snips 7 | # 8 | # Modelled after Python’s os.path.join 9 | # https://docs.python.org/3.7/library/os.path.html#os.path.join 10 | # Windows not supported 11 | function(join_paths joined_path first_path_segment) 12 | set(temp_path "${first_path_segment}") 13 | foreach(current_segment IN LISTS ARGN) 14 | if(NOT ("${current_segment}" STREQUAL "")) 15 | if(IS_ABSOLUTE "${current_segment}") 16 | set(temp_path "${current_segment}") 17 | else() 18 | set(temp_path "${temp_path}/${current_segment}") 19 | endif() 20 | endif() 21 | endforeach() 22 | set(${joined_path} "${temp_path}" PARENT_SCOPE) 23 | endfunction() 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 - Giuseppe Persico 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | curlcpp 2 | ======= 3 | 4 | An object-oriented C++ wrapper for cURL tool 5 | 6 | If you want to know a bit more about cURL and libcurl, you should go on the official website http://curl.haxx.se/ 7 | 8 | Donate 9 | ====== 10 | 11 | Help me to improve this project! 12 | 13 | Donate button 14 | 15 | 16 | 17 | Compile and link manually 18 | ========================= 19 | 20 | Standalone (static library) 21 | ---------- 22 | 23 | ```bash 24 | cd build 25 | cmake .. 26 | make 27 | ``` 28 | 29 | Standalone (dynamic/shared library) 30 | ---------- 31 | 32 | ```bash 33 | cd build 34 | cmake .. -DBUILD_SHARED_LIBS=SHARED 35 | make 36 | ``` 37 | 38 | **Note:** cURL >= 7.34.0 is required. 39 | 40 | When linking curlcpp to your application don't forget to also link `curl`. Example: 41 | 42 | ```bash 43 | g++ -std=c++11 example.cpp -I/usr/local/include/curlcpp/ -lcurlcpp -lcurl 44 | ``` 45 | 46 | Submodule 47 | --------- 48 | 49 | When using a git submodule and CMake-buildsystem, add the following lines to your `CMakeLists.txt`: 50 | 51 | ``` 52 | ADD_SUBDIRECTORY(ext/curlcpp) # Change `ext/curlcpp` to a directory according to your setup 53 | INCLUDE_DIRECTORIES(${CURLCPP_SOURCE_DIR}/include) 54 | ``` 55 | 56 | 57 | Install via Homebrew 58 | ==================== 59 | 60 | curlcpp is now available also via homebrew package manager: 61 | 62 | ```bash 63 | brew install curlcpp 64 | ``` 65 | 66 | 67 | Examples 68 | ======== 69 | 70 | Here are some usage examples. You will find more examples in the test folder! 71 | 72 | Here's an example of a simple HTTP request to get google web page, using the curl_easy interface: 73 | 74 | * ### Simple request 75 | 76 | `````c++ 77 | #include "curlcpp/curl_easy.h" 78 | 79 | using curl::curl_easy; 80 | using curl::curl_easy_exception; 81 | using curl::curlcpp_traceback; 82 | 83 | /** 84 | * This example shows how to make a simple request with curl. 85 | */ 86 | int main() { 87 | // Easy object to handle the connection. 88 | curl_easy easy; 89 | 90 | // Add some options. 91 | easy.add("http://"); 92 | easy.add(1L); 93 | 94 | try { 95 | easy.perform(); 96 | } catch (curl_easy_exception &error) { 97 | // If you want to print the last error. 98 | std::cerr< ios(stream); 130 | 131 | // Declaration of an easy object 132 | curl_easy easy(ios); 133 | 134 | // Add some option to the curl_easy object. 135 | easy.add("http://"); 136 | easy.add(1L); 137 | 138 | try { 139 | easy.perform(); 140 | 141 | // Retrieve information about curl current session. 142 | auto x = easy.get_info(); 143 | 144 | /** 145 | * get_info returns a curl_easy_info object. With the get method we retrieve 146 | * the std::pair object associated with it: the first item is the return code of the 147 | * request. The second is the element requested by the specified libcurl macro. 148 | */ 149 | std::cout< 168 | 169 | #include "curlcpp/curl_easy.h" 170 | #include "curlcpp/curl_pair.h" 171 | #include "curlcpp/curl_form.h" 172 | #include "curlcpp/curl_exception.h" 173 | 174 | using std::string; 175 | 176 | using curl::curl_form; 177 | using curl::curl_easy; 178 | using curl::curl_pair; 179 | using curl::curl_easy_exception; 180 | using curl::curlcpp_traceback; 181 | 182 | int main(int argc, const char * argv[]) { 183 | curl_form form; 184 | curl_easy easy; 185 | 186 | // Forms creation 187 | curl_pair name_form(CURLFORM_COPYNAME,"user"); 188 | curl_pair name_cont(CURLFORM_COPYCONTENTS,"you username here"); 189 | curl_pair pass_form(CURLFORM_COPYNAME,"passw"); 190 | curl_pair pass_cont(CURLFORM_COPYCONTENTS,"your password here"); 191 | 192 | try { 193 | // Form adding 194 | form.add(name_form,name_cont); 195 | form.add(pass_form,pass_cont); 196 | 197 | // Add some options to our request 198 | easy.add("http://"); 199 | easy.add(false); 200 | easy.add(form.get()); 201 | // Execute the request. 202 | easy.perform(); 203 | 204 | } catch (curl_easy_exception &error) { 205 | // If you want to get the entire error stack we can do: 206 | curlcpp_traceback errors = error.get_traceback(); 207 | // Otherwise we could print the stack like this: 208 | error.print_traceback(); 209 | } 210 | return 0; 211 | } 212 | ````` 213 | 214 | * ### Store response in a file 215 | 216 | And if we would like to put the returned content in a file? Nothing easier than: 217 | 218 | `````c++ 219 | #include 220 | #include 221 | #include 222 | 223 | #include "curlcpp/curl_easy.h" 224 | #include "curlcpp/curl_ios.h" 225 | #include "curlcpp/curl_exception.h" 226 | 227 | using std::cout; 228 | using std::endl; 229 | using std::ostream; 230 | using std::ofstream; 231 | 232 | using curl::curl_easy; 233 | using curl::curl_ios; 234 | using curl::curl_easy_exception; 235 | using curl::curlcpp_traceback; 236 | 237 | int main(int argc, const char * argv[]) { 238 | // Create a file 239 | ofstream myfile; 240 | myfile.open ("/path/to/your/file"); 241 | 242 | // Create a curl_ios object to handle the stream 243 | curl_ios writer(myfile); 244 | // Pass it to the easy constructor and watch the content returned in that file! 245 | curl_easy easy(writer); 246 | 247 | // Add some option to the easy handle 248 | easy.add("http://"); 249 | easy.add(1L); 250 | try { 251 | // Execute the request 252 | easy.perform(); 253 | 254 | } catch (curl_easy_exception &error) { 255 | // If you want to print the last error. 256 | std::cerr< 272 | #include 273 | 274 | #include "curlcpp/curl_easy.h" 275 | #include "curlcpp/curl_form.h" 276 | #include "curlcpp/curl_ios.h" 277 | #include "curlcpp/curl_exception.h" 278 | 279 | using std::cout; 280 | using std::endl; 281 | using std::ostringstream; 282 | 283 | using curl::curl_easy; 284 | using curl::curl_ios; 285 | using curl::curl_easy_exception; 286 | using curl::curlcpp_traceback; 287 | 288 | int main() { 289 | // Create a stringstream object 290 | ostringstream str; 291 | // Create a curl_ios object, passing the stream object. 292 | curl_ios writer(str); 293 | 294 | // Pass the writer to the easy constructor and watch the content returned in that variable! 295 | curl_easy easy(writer); 296 | // Add some option to the easy handle 297 | easy.add("http://"); 298 | easy.add(1L); 299 | 300 | try { 301 | easy.perform(); 302 | 303 | // Let's print the stream content 304 | cout< 324 | #include 325 | 326 | #include "curlcpp/curl_easy.h" 327 | #include "curlcpp/curl_form.h" 328 | #include "curlcpp/curl_pair.h" 329 | #include "curlcpp/curl_receiver.h" 330 | #include "curlcpp/curl_exception.h" 331 | #include "curlcpp/curl_sender.h" 332 | 333 | using std::cout; 334 | using std::endl; 335 | using std::string; 336 | 337 | using curl::curl_form; 338 | using curl::curl_easy; 339 | using curl::curl_sender; 340 | using curl::curl_receiver; 341 | using curl::curl_easy_exception; 342 | using curl::curlcpp_traceback; 343 | 344 | int main(int argc, const char * argv[]) { 345 | // Simple request 346 | string request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n"; 347 | // Creation of easy object. 348 | curl_easy easy; 349 | try { 350 | easy.add("http://"); 351 | // Just connect 352 | easy.add(true); 353 | // Execute the request. 354 | easy.perform(); 355 | 356 | } catch (curl_easy_exception &error) { 357 | // If you want to get the entire error stack we can do: 358 | curlcpp_traceback errors = error.get_traceback(); 359 | // Otherwise we could print the stack like this: 360 | error.print_traceback(); 361 | } 362 | 363 | // Creation of a sender. You should wait here using select to check if socket is ready to send. 364 | curl_sender sender(easy); 365 | sender.send(request); 366 | // Prints che sent bytes number. 367 | cout<<"Sent bytes: "< receiver; 374 | // Receive the content on the easy handler 375 | receiver.receive(easy); 376 | // Prints the received bytes number. 377 | cout<<"Receiver bytes: "< 397 | #include 398 | 399 | #include "curlcpp/curl_easy.h" 400 | #include "curlcpp/curl_multi.h" 401 | #include "curlcpp/curl_ios.h" 402 | 403 | using curl::curl_easy; 404 | using curl::curl_multi; 405 | using curl::curl_ios; 406 | using curl::curl_easy_exception; 407 | using curl::curlcpp_traceback; 408 | 409 | /** 410 | * This example shows how to make multiple requests 411 | * using curl_multi interface. 412 | */ 413 | int main() { 414 | std::vector urls; 415 | urls.emplace_back("https://google.com"); 416 | urls.emplace_back("https://facebook.com"); 417 | urls.emplace_back("https://linkedin.com"); 418 | 419 | // Create a vector of curl easy handlers. 420 | std::vector handlers; 421 | 422 | // Create a vector of curl streams. 423 | std::vector> streams; 424 | 425 | // Create the curl easy handler and associated the streams with it. 426 | for (const auto & url : urls) { 427 | auto *output_stream = new std::ostringstream; 428 | curl_ios curl_stream(*output_stream); 429 | 430 | curl_easy easy(curl_stream); 431 | easy.add(url.c_str()); 432 | easy.add(1L); 433 | 434 | streams.emplace_back(curl_stream); 435 | handlers.emplace_back(easy); 436 | } 437 | 438 | // Create a map of curl pointers to output streams. 439 | std::unordered_map*> easy_streams; 440 | for (int i = 0; i < handlers.size(); ++i) { 441 | easy_streams[handlers.at(i).get_curl()] = (curl_ios*)&streams.at(i); 442 | } 443 | 444 | // Add all the handlers to the curl multi object. 445 | curl_multi multi; 446 | multi.add(handlers); 447 | 448 | try { 449 | // Start the transfers. 450 | multi.perform(); 451 | 452 | // Until there are active transfers, call the perform() API. 453 | while (multi.get_active_transfers()) { 454 | multi.perform(); 455 | 456 | // Extracts the first finished request. 457 | std::unique_ptr message = multi.get_next_finished(); 458 | if (message != nullptr) { 459 | const curl_easy *handler = message->get_handler(); 460 | 461 | // Get the stream associated with the curl easy handler. 462 | curl_ios stream_handler = *easy_streams[handler->get_curl()]; 463 | 464 | auto content = stream_handler.get_stream()->str(); 465 | auto url = handler->get_info(); 466 | auto response_code = handler->get_info(); 467 | auto content_type = handler->get_info(); 468 | auto http_code = handler->get_info(); 469 | 470 | std::cout << "CODE: " << response_code.get() 471 | << ", TYPE: " << content_type.get() 472 | << ", HTTP_CODE: " << http_code.get() 473 | << ", URL: " << url.get() 474 | << ", CONTENT: " << content.substr(0, 10) + " ... " 475 | << std::endl; 476 | } 477 | } 478 | 479 | // Free the memory allocated for easy streams. 480 | for (auto stream : streams) { 481 | delete stream.get_stream(); 482 | } 483 | 484 | } catch (curl_easy_exception &error) { 485 | // If you want to print the last error. 486 | std::cerr< 30 | 31 | #include "curl_exception.h" 32 | #include "cookie_datetime.h" 33 | 34 | namespace curl { 35 | /** 36 | * This class allows to specify every single field of an http-style cookie. 37 | */ 38 | class cookie { 39 | public: 40 | /** 41 | * Default constructor. 42 | */ 43 | cookie() = default; 44 | /** 45 | * The overloaded constructor allow a fast way to build a cookie. 46 | */ 47 | cookie(const std::string&, const std::string&, const cookie_datetime &, 48 | const std::string& = "", const std::string& = "", bool = false); 49 | /** 50 | * This constructor overloades the previous one. 51 | */ 52 | cookie(const char *, const char *, const cookie_datetime &, const char * = "", 53 | const char * = "", bool = false); 54 | /** 55 | * This method allows to specify the cookie name. 56 | */ 57 | cookie *set_name(const std::string&); 58 | /** 59 | * This method overloads the previous one allowing to specify a const char * 60 | * instead of a string. 61 | */ 62 | cookie *set_name(const char *); 63 | /** 64 | * This method allows to specify the cookie value. 65 | */ 66 | cookie *set_value(const std::string&); 67 | /** 68 | * This method allows to specify the cookie value, 69 | */ 70 | cookie *set_value(const char *); 71 | /** 72 | * This method allows to specify the cookie path. 73 | */ 74 | cookie *set_path(const std::string&) NOEXCEPT; 75 | /** 76 | * This method overloads the previous one allowing to specify a const char * 77 | * instead of a string. 78 | */ 79 | cookie *set_path(const char *) NOEXCEPT; 80 | /** 81 | * This method allows to specify the cookie domain. 82 | */ 83 | cookie *set_domain(const std::string&) NOEXCEPT; 84 | /** 85 | * This method overloads the previous one allowing to specify a const char * 86 | * instead of a string. 87 | */ 88 | cookie *set_domain(const char *) NOEXCEPT; 89 | /** 90 | * This method allows to specify the cookie security. 91 | */ 92 | cookie *set_secure(bool) NOEXCEPT; 93 | /** 94 | * This method overloads the previous one allowing to specify an integer instead 95 | * of a bool. 96 | */ 97 | cookie *set_secure(unsigned int); 98 | /** 99 | * This method overloads the previous one allowing to specify a string to indicate 100 | * whether the cookie is secure (with "secure" keyword) or not (empty string). 101 | */ 102 | cookie *set_secure(const std::string&) NOEXCEPT; 103 | /** 104 | * This method overloads the previous one allowing to specify a string to indicate 105 | * whether the cookie is secure (with "secure" keyword) or not (empty string). 106 | */ 107 | cookie *set_secure(const char *) NOEXCEPT; 108 | /** 109 | * This method allows to specify a datetime expiration to this cookie. 110 | */ 111 | cookie *set_datetime(const cookie_datetime &) NOEXCEPT; 112 | /** 113 | * This method returns the cookie name. 114 | */ 115 | std::string get_name() const NOEXCEPT; 116 | /** 117 | * This method returns the cookie value. 118 | */ 119 | std::string get_value() const NOEXCEPT; 120 | /** 121 | * This method returns the cookie path. 122 | */ 123 | std::string get_path() const NOEXCEPT; 124 | /** 125 | * This method returns the cookie domain. 126 | */ 127 | std::string get_domain() const NOEXCEPT; 128 | /** 129 | * This method returns the datetime expire object for this cookie. 130 | */ 131 | cookie_datetime get_datetime() const NOEXCEPT; 132 | /** 133 | * This method returns the cookie security. 134 | */ 135 | bool is_secure() const NOEXCEPT; 136 | /** 137 | * This method allows to get a string representing the entire cookie. Example: 138 | * 'Set-cookie: name=xxx; path=/; domain=/ expires=date' 139 | */ 140 | std::string get_formatted() NOEXCEPT; 141 | private: 142 | /** 143 | * The cookie name. 144 | */ 145 | std::string name; 146 | /** 147 | * Il valore del cookie. 148 | */ 149 | std::string value; 150 | /** 151 | * The cookie path. 152 | */ 153 | std::string path; 154 | /** 155 | * The cookie domain. 156 | */ 157 | std::string domain; 158 | /** 159 | * The cookie expire date and time. 160 | */ 161 | cookie_datetime datetime; 162 | /** 163 | * The cookie security. 164 | */ 165 | bool secure; 166 | }; 167 | } 168 | 169 | #endif //CURLCPP_COOKIE_H -------------------------------------------------------------------------------- /include/cookie_date.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - cookie_date.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_COOKIE_DATE_H 27 | #define CURLCPP_COOKIE_DATE_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "curl_config.h" 35 | 36 | namespace curl { 37 | // Enumeration to better define months. 38 | enum months { JANUARY = 1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER}; 39 | // Enumeration to better define week days. 40 | enum weekdays {MONDAY = 1, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}; 41 | 42 | // Leave this alone :) 43 | namespace details { 44 | // Map months numbers with months short names (cookies likes it short XD) 45 | static const std::map monthsNames = { 46 | {JANUARY,"Jan"}, {FEBRUARY,"Feb"}, {MARCH,"Mar"}, {APRIL,"Apr"}, {MAY,"May"}, {JUNE,"Jun"}, 47 | {JULY,"Jul"},{AUGUST,"Aug"},{SEPTEMBER,"Sep"},{OCTOBER,"Oct"},{NOVEMBER,"Nov"},{DECEMBER,"Dec"} 48 | }; 49 | // Map week days numbers with days short names (cookies likes it, still, short XD) 50 | static const std::map weekdayNames = { 51 | {MONDAY,"Mon"}, {TUESDAY,"Tue"}, {WEDNESDAY,"Wed"}, {THURSDAY,"Thu"}, {FRIDAY,"Fri"}, {SATURDAY,"Sat"}, 52 | {SUNDAY,"Sun"} 53 | }; 54 | } 55 | 56 | /** 57 | * This class provide an easy way to build a date formed by day, month and year 58 | */ 59 | class cookie_date { 60 | public: 61 | /** 62 | * Default constructor. Inizialize the attributes with default values. 63 | */ 64 | cookie_date() : day(1), month("Jan"), week_day("Mon"), year(1970) {} 65 | /** 66 | * Constructor with parameters, which gives a fast way to build a cookie_date object. 67 | */ 68 | cookie_date(unsigned int, unsigned int, unsigned int, unsigned int) NOEXCEPT; 69 | /** 70 | * This method allows to specify the week dayname for the date. If the day is less or equal 71 | * than zero or greater than 7, 1 will be choosen 72 | */ 73 | cookie_date *set_week_day(unsigned int) NOEXCEPT; 74 | /** 75 | * This method allows to specify a day for the date. If the day is less than zero or 76 | * greater than 31, 1 will be choosen. 77 | */ 78 | cookie_date *set_day(unsigned int) NOEXCEPT; 79 | /** 80 | * This method allows to specify a month for the date. If the month is not supported, 81 | * January will be choosen. 82 | */ 83 | cookie_date *set_month(unsigned int); 84 | /** 85 | * This method allows to specify a year for the date. If year is less than 1970, 1970 will 86 | * be choosen. 87 | */ 88 | cookie_date *set_year(unsigned int) NOEXCEPT; 89 | /** 90 | * This method returns the week day name 91 | */ 92 | std::string get_week_day() const NOEXCEPT; 93 | /** 94 | * This method returns the day number. 95 | */ 96 | unsigned int get_day() const NOEXCEPT; 97 | /** 98 | * This method returns the month name. 99 | */ 100 | std::string get_month() const NOEXCEPT; 101 | /** 102 | * This method returns the year number. 103 | */ 104 | unsigned int get_year() const NOEXCEPT; 105 | /** 106 | * This method returns the date formatted as day-month-year 107 | */ 108 | std::string get_formatted() NOEXCEPT; 109 | private: 110 | /** 111 | * The day for this date. 112 | */ 113 | unsigned int day; 114 | /** 115 | * The month name. 116 | */ 117 | std::string month; 118 | /** 119 | * The week dayname. 120 | */ 121 | std::string week_day; 122 | /** 123 | * The month year. 124 | */ 125 | unsigned int year; 126 | }; 127 | } 128 | 129 | #endif //CURLCPP_COOKIE_DATE_H 130 | -------------------------------------------------------------------------------- /include/cookie_datetime.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - cookie_datetime.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_COOKIE_DATETIME_H 27 | #define CURLCPP_COOKIE_DATETIME_H 28 | 29 | #include "cookie_date.h" 30 | #include "cookie_time.h" 31 | 32 | namespace curl { 33 | /** 34 | * This class provide an easy way to specify the date and the time of cooking expiration. 35 | */ 36 | class cookie_datetime { 37 | public: 38 | /** 39 | * Default constructor. 40 | */ 41 | cookie_datetime() = default; 42 | /** 43 | * The constructor with parameters allows to specify a time and a date for cookie expiration. 44 | */ 45 | cookie_datetime(const cookie_time &, const cookie_date &) NOEXCEPT; 46 | /** 47 | * This method allows to set the expiration time. 48 | */ 49 | cookie_datetime *set_time(const cookie_time &) NOEXCEPT; 50 | /** 51 | * This method allows to set the expiration date. 52 | */ 53 | cookie_datetime *set_date(const cookie_date &) NOEXCEPT; 54 | /** 55 | * This method returns the time object. 56 | */ 57 | cookie_time get_time() const NOEXCEPT; 58 | /** 59 | * This method returns the date object. 60 | */ 61 | cookie_date get_date() const NOEXCEPT; 62 | /** 63 | * This method returns the cookie_datetime as a string. 64 | */ 65 | std::string get_formatted() NOEXCEPT; 66 | private: 67 | /** 68 | * Time object. 69 | */ 70 | cookie_time time; 71 | /** 72 | * Date object. 73 | */ 74 | cookie_date date; 75 | }; 76 | } 77 | 78 | #endif //CURLCPP_COOKIE_DATETIME_H -------------------------------------------------------------------------------- /include/cookie_time.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - cookie_time.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_COOKIE_TIME_H 27 | #define CURLCPP_COOKIE_TIME_H 28 | 29 | #include "curl_config.h" 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | namespace curl { 36 | /** 37 | * This class provides a fast way to build a time object formed by hour, minutes and seconds. 38 | */ 39 | class cookie_time { 40 | public: 41 | /** 42 | * The default constructor will initialize every attribute with zero. 43 | */ 44 | cookie_time() : hour(0), minutes(0), seconds(0) {}; 45 | /** 46 | * The constructor with parameters allows to initialize attributes with custom values. 47 | */ 48 | cookie_time(unsigned int, unsigned int, unsigned int); 49 | /** 50 | * This method allows to specify the hours. 51 | */ 52 | cookie_time *set_hour(unsigned int) NOEXCEPT; 53 | /** 54 | * This method allows to specify the minutes. 55 | */ 56 | cookie_time *set_minutes(unsigned int) NOEXCEPT; 57 | /** 58 | * This method allows to specify the seconds. 59 | */ 60 | cookie_time *set_seconds(unsigned int) NOEXCEPT; 61 | /** 62 | * This method returns the hours. 63 | */ 64 | unsigned int get_hour() const NOEXCEPT; 65 | /** 66 | * This method returns the minutes. 67 | */ 68 | unsigned int get_minutes() const NOEXCEPT; 69 | /** 70 | * This method returns the seconds. 71 | */ 72 | unsigned int get_seconds() const NOEXCEPT; 73 | /** 74 | * This method returns the time formatted as h:m:s 75 | */ 76 | std::string get_formatted() const NOEXCEPT; 77 | private: 78 | /** 79 | * The hours. 80 | */ 81 | unsigned int hour; 82 | /** 83 | * The minutes. 84 | */ 85 | unsigned int minutes; 86 | /** 87 | * The seconds. 88 | */ 89 | unsigned int seconds; 90 | }; 91 | } 92 | 93 | #endif //CURLCPP_COOKIE_TIME_H -------------------------------------------------------------------------------- /include/curl_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 - Qiangqiang Wu, Ferdinand Thiessen 5 | * File - cookie_config.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_CONFIG_H 27 | #define CURLCPP_CURL_CONFIG_H 28 | 29 | #if defined(_MSC_VER) 30 | #define NOEXCEPT 31 | #include 32 | #else 33 | #define NOEXCEPT noexcept 34 | #endif 35 | 36 | #endif /* defined(CURLCPP_CURL_CONFIG_H) */ -------------------------------------------------------------------------------- /include/curl_cookie.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_cookie.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURL_COOKIE_H 27 | #define CURL_COOKIE_H 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "curl_easy.h" 34 | #include "cookie.h" 35 | 36 | namespace curl { 37 | // Typedef to enhance readability. 38 | using curlcpp_cookies = std::vector; 39 | /** 40 | * This class represents a generic cookie handler. It allows a user to get 41 | * and set cookie for a domain, in an easy way and without caring about resources 42 | * allocation and deallocation. 43 | */ 44 | class curl_cookie { 45 | public: 46 | /** 47 | * This constructor allow you to specify a curl_easy object. 48 | */ 49 | explicit curl_cookie(curl_easy &easy) : easy(easy) {} 50 | /** 51 | * This method allow you to set the cookie file from where to read initial cookies. 52 | * If you pass an empty string or a string containing a non existing file's path, 53 | * the cookie engine will be initialized, but without reading initial cookies. 54 | */ 55 | void set_file(const std::string&); 56 | /** 57 | * This method allow you to specify a string that represents a cookie. Such a cookie 58 | * can be either a single line in Netscape / Mozilla format or just regular HTTP-style 59 | * header (Set-Cookie: ...) format. This will also enable the cookie engine. This adds 60 | * that single cookie to the internal cookie store. 61 | */ 62 | void set(curl::cookie &); 63 | /** 64 | * This method overloads the one previously declared allowing to specify a vector of cookies. 65 | */ 66 | void set(const std::vector &); 67 | /** 68 | * This method allow you to get all known cookies for a specific domain. 69 | */ 70 | curlcpp_cookies get() const NOEXCEPT; 71 | /** 72 | * This method erases all cookies held in memory. 73 | */ 74 | void erase(); 75 | /** 76 | * This method writes all the cookies held in memory to the file specifiied with 77 | * set_cookiejar_file method. 78 | */ 79 | void flush(); 80 | /** 81 | * This method erases all the session cookies held in memory. 82 | */ 83 | void erase_session(); 84 | /** 85 | * This method loads all the cookies from the file specified with set_cookie_file method. 86 | */ 87 | void reload(); 88 | private: 89 | /** 90 | * Istance on curl_easy class. 91 | */ 92 | curl_easy &easy; 93 | }; 94 | } 95 | 96 | #endif /* CURL_COOKIE_H */ -------------------------------------------------------------------------------- /include/curl_easy_info.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_easy_info.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURL_EASY_INFO_H 27 | #define CURL_EASY_INFO_H 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | namespace curl { 34 | /** 35 | * This object contains a pair which contains curl easy get_info result. 36 | */ 37 | template class curl_easy_info { 38 | public: 39 | explicit curl_easy_info(T pointer) : _pointer(pointer) {} 40 | 41 | T get() const { 42 | return _pointer; 43 | } 44 | private: 45 | T _pointer; 46 | }; 47 | 48 | /** 49 | * Template specialization for char * 50 | */ 51 | template<> class curl_easy_info { 52 | public: 53 | explicit curl_easy_info(char *pointer) : _pointer(pointer) {} 54 | 55 | std::string get() const { 56 | if (_pointer == nullptr) { 57 | return std::string(""); 58 | } 59 | return std::string(_pointer); 60 | } 61 | private: 62 | char *_pointer; 63 | }; 64 | 65 | /** 66 | * Template specialization for struct curl_slist *. 67 | */ 68 | template<> class curl_easy_info { 69 | public: 70 | explicit curl_easy_info(struct curl_slist *pointer) : _pointer(pointer) {} 71 | 72 | ~curl_easy_info() { 73 | if (_pointer != nullptr) { 74 | curl_slist_free_all(_pointer); 75 | } 76 | } 77 | std::vector get() { 78 | struct curl_slist *backup = _pointer; 79 | std::vector infos; 80 | while (backup != nullptr) { 81 | if (backup->data != nullptr) { 82 | std::string str(backup->data); 83 | infos.push_back(str); 84 | } 85 | backup = backup->next; 86 | } 87 | return infos; 88 | } 89 | private: 90 | struct curl_slist *_pointer; 91 | }; 92 | } 93 | 94 | #endif /* CURL_EASY_INFO_H */ 95 | -------------------------------------------------------------------------------- /include/curl_exception.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_exception.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_EXCEPTION_H 27 | #define CURLCPP_CURL_EXCEPTION_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "curl_config.h" 39 | 40 | namespace curl { 41 | // We like it short. 42 | using curlcpp_traceback_object = std::pair; 43 | using curlcpp_traceback = std::vector; 44 | 45 | /** 46 | * This class represents a custom exception for libcurl errors. 47 | * If a function throws an error, its name will be added to a 48 | * vector (treated like a stack, because if I had used a stack, 49 | * to print it, I should have to remove all the elements), so 50 | * users can keep track of which method threw which exception. 51 | */ 52 | class curl_exception : public std::runtime_error { 53 | public: 54 | /** 55 | * This constructor is used to build the error. 56 | */ 57 | curl_exception(const std::string&, const std::string&) NOEXCEPT; 58 | /** 59 | * The copy constructor allows to copy the object in a thread safe way. 60 | */ 61 | curl_exception(const curl_exception &) NOEXCEPT; 62 | /** 63 | * The assignment operator allows to assign the object to another object in 64 | * a thread safe way. 65 | */ 66 | curl_exception & operator=(curl_exception const&); 67 | /** 68 | * The destructor, in this case, doesn't do anything. 69 | */ 70 | ~curl_exception() NOEXCEPT override = default; 71 | 72 | using std::exception::what; 73 | /** 74 | * Returns the vector of errors. 75 | */ 76 | static curlcpp_traceback get_traceback() ; 77 | /** 78 | * Simple method which prints the entire error stack. 79 | */ 80 | static void print_traceback() ; 81 | /** 82 | * Simple method which clears the entire error stack. 83 | */ 84 | static void clear_traceback() ; 85 | /** 86 | * Simple method which clears the error stack saving it (before cleaning) in a 87 | * traceback specified in input. 88 | */ 89 | static void clear_traceback(curlcpp_traceback &) ; 90 | private: 91 | /** 92 | * The error container must be static or will be cleared 93 | * when an exception is thrown. 94 | */ 95 | static curlcpp_traceback traceback; 96 | 97 | /** 98 | * Locker for inserting traceback. 99 | */ 100 | static std::mutex tracebackLocker; 101 | }; 102 | 103 | // Implementation of print_traceback 104 | inline void curl_exception::print_traceback() { 105 | curl_exception::tracebackLocker.lock(); 106 | std::for_each(curl_exception::traceback.begin(),curl_exception::traceback.end(), 107 | [](const curlcpp_traceback_object &value) { 108 | 109 | std::cout<<"ERROR: "< 30 | #include 31 | #include 32 | 33 | #include "curl_config.h" 34 | #include "curl_exception.h" 35 | #include "curl_pair.h" 36 | 37 | namespace curl { 38 | 39 | /** 40 | * This class simplifies the creation of a form. It wraps all the libcurl 41 | * functions used to add content to a form and to destroy it. 42 | */ 43 | class curl_form { 44 | public: 45 | /** 46 | * The default constructor will simply initialize the pointers to the 47 | * list of form contents. 48 | */ 49 | curl_form(); 50 | /** 51 | * The destructor will free the space allocated for the form content 52 | * list. 53 | */ 54 | ~curl_form() NOEXCEPT; 55 | /** 56 | * Copy constructor used to perform a deep copy of the form content 57 | * list. Without it we would not be able to perform the copy. 58 | */ 59 | curl_form(const curl_form &); 60 | /** 61 | * Assignment operator to implement assignment between two objects 62 | * of this class. 63 | */ 64 | curl_form &operator=(const curl_form &); 65 | /** 66 | * This method allows users to add content to a form, using the 67 | * curl_pair class. 68 | */ 69 | void add(const curl_pair &, const curl_pair &); 70 | /** 71 | * Overloaded add method. 72 | */ 73 | void add(const curl_pair &, 74 | const curl_pair &, const curl_pair &); 75 | /** 76 | * Overloaded add method. It adds another curl_pair object to add more 77 | * contents to the form contents list. 78 | */ 79 | void add(const curl_pair &, 80 | const curl_pair &, const curl_pair &); 81 | /** 82 | * Overloaded add method. It adds another curl_pair object to add more 83 | * contents to the form contents list. 84 | */ 85 | void add(const curl_pair &, 86 | const curl_pair &, const curl_pair &); 87 | /** 88 | * Overloaded add method. It adds another curl_pair object to add more 89 | * contents to the form contents list. 90 | */ 91 | void add(const curl_pair &,const curl_pair &, 92 | const curl_pair &, const curl_pair &); 93 | /** 94 | * Overloaded add method. Used primarily to pass data via CURLFORM_BUFFERPTR. 95 | * E.g. first option is content name, second is buffer name, 96 | * third is buffer data pointer, fourth is buffer length. 97 | */ 98 | void add(const curl_pair &, const curl_pair &, 99 | const curl_pair &, const curl_pair &); 100 | /** 101 | * Overloaded add method. This version is primarily used to upload multiple files. 102 | * You can pass a vector of filenames to upload them. 103 | */ 104 | void add(const curl_pair &, const std::vector &); 105 | /** 106 | * Simple getter method used to return the head of the list. 107 | */ 108 | const struct curl_httppost *get() const; 109 | protected: 110 | /** 111 | * This utility function is used to check if a given pointer is null. 112 | */ 113 | template void is_null(const T *ptr) const; 114 | /** 115 | * This utility function is used to perform a deep copy of 116 | * the form contents list. We must traverse the new list to 117 | * copy all the field in the left-object's list. This method 118 | * puts the node in the tail. Indeed, libcurl keeps two 119 | * pointers to implement this list: a tail and a head. 120 | */ 121 | void copy_ptr(struct curl_httppost **, const struct curl_httppost *); 122 | private: 123 | struct curl_httppost *form_post; 124 | struct curl_httppost *last_ptr; 125 | }; 126 | 127 | // Implementation of copy constructor. 128 | inline curl_form::curl_form(const curl_form &form) : form_post(nullptr), last_ptr(nullptr) { 129 | *this = form; 130 | } 131 | 132 | // Implementation of utility function to check if a pointer points to null. 133 | template inline void curl_form::is_null(const T *ptr) const { 134 | if (ptr == nullptr) { 135 | throw std::bad_alloc(); 136 | } 137 | } 138 | 139 | // Implementation of getter method that returns the list head. 140 | inline const struct curl_httppost *curl_form::get() const { 141 | return this->form_post; 142 | } 143 | 144 | /** 145 | * Re-declaring template curl_pair, in case this is not in include path 146 | */ 147 | template class curl_pair; 148 | 149 | /** 150 | * Template specialization of curl_pair for curl_form type. 151 | */ 152 | template class curl_pair { 153 | public: 154 | /** 155 | * The two parameters constructor gives users a fast way to build an object of 156 | * this type. 157 | */ 158 | curl_pair(const T option, const curl_form &value) : option(option), value(value) {} 159 | /** 160 | * Simple method that returns the first field of the pair. 161 | */ 162 | inline T first() const NOEXCEPT { 163 | return this->option; 164 | } 165 | /** 166 | * Simple method that returns the second field of the pair as a 167 | * C struct curl_httppost pointer. 168 | */ 169 | inline const curl_httppost *second() const NOEXCEPT { 170 | return (this->value).get(); 171 | } 172 | private: 173 | const T option; 174 | const curl_form &value; 175 | }; 176 | 177 | 178 | } 179 | 180 | #endif /* defined(CURLCPP_CURL_FORM_H) */ 181 | -------------------------------------------------------------------------------- /include/curl_global.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_global.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_GLOBAL_H 27 | #define CURLCPP_CURL_GLOBAL_H 28 | 29 | #include 30 | #include "curl_exception.h" 31 | 32 | namespace curl { 33 | /** 34 | * This class provides global initialization of curl so that use of all curl 35 | * interfaces is thread safe. 36 | */ 37 | class curl_global { 38 | public: 39 | /** 40 | * The default constructor will initialize the curl 41 | * environment with the default flag. 42 | */ 43 | curl_global(); 44 | /** 45 | * Overloaded constructor that initializes curl environment 46 | * with user specified flag. 47 | */ 48 | explicit curl_global(long); 49 | 50 | /** 51 | * Copying disabled to follow RAII idiom. 52 | */ 53 | curl_global(const curl_global&) = delete; 54 | curl_global& operator=(const curl_global&) = delete; 55 | 56 | /** 57 | * The virtual destructor will provide an easy and clean 58 | * way to deallocate resources, closing curl environment 59 | * correctly. 60 | */ 61 | virtual ~curl_global(); 62 | }; 63 | } 64 | 65 | #endif /* defined(CURLCPP_CURL_GLOBAL_H) */ 66 | -------------------------------------------------------------------------------- /include/curl_header.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_header.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_HEADER_H 27 | #define CURLCPP_CURL_HEADER_H 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "curl_config.h" 34 | 35 | namespace curl { 36 | 37 | /** 38 | * This class represents a generic header. It allows a user to add 39 | * headers without caring about deallocation of resources. 40 | */ 41 | class curl_header { 42 | public: 43 | /** 44 | * The default constructor will initialize the headers list 45 | * with nullptr. 46 | */ 47 | curl_header(); 48 | /** 49 | * Overloaded constructor that allows users to initialize the 50 | * headers list with a list of values. 51 | */ 52 | curl_header(std::initializer_list); 53 | /** 54 | * Copy constructor. Performs a deep copy of the headers list. 55 | */ 56 | curl_header(const curl_header &); 57 | /** 58 | * Assignment operator to perform assignment between object of 59 | * this class type. 60 | */ 61 | curl_header &operator=(const curl_header &); 62 | /** 63 | * The destructor will deallocate the resources used to handle 64 | * the headers list. 65 | */ 66 | ~curl_header() NOEXCEPT; 67 | /** 68 | * This method allows users to add a header as string. 69 | */ 70 | void add(const std::string&); 71 | /** 72 | * This method allows users to add headers specifying an iterable 73 | * data structure containing the headers to add. 74 | */ 75 | template void add(Iterator, Iterator); 76 | /** 77 | * Simple getter method that returns the pointer to the headers 78 | * list. 79 | */ 80 | const struct curl_slist *get() const; 81 | private: 82 | int size; 83 | struct curl_slist *headers; 84 | }; 85 | 86 | // Implementation of get method. 87 | inline const struct curl_slist *curl_header::get() const { 88 | return this->headers; 89 | } 90 | 91 | // Implementation of copy constructor. 92 | inline curl_header::curl_header(const curl_header &header) : size(0), headers(nullptr) { 93 | *this = header; 94 | } 95 | 96 | // Implementation of overloaded add method. 97 | template void curl_header::add(Iterator begin, const Iterator end) { 98 | for (; begin != end; ++begin) { 99 | this->add(*begin); 100 | } 101 | } 102 | 103 | /** 104 | * Re-declaring template curl_pair, in case this is not in include path 105 | */ 106 | template class curl_pair; 107 | 108 | /** 109 | * Template specialization of curl_pair for curl_header type. 110 | */ 111 | template class curl_pair { 112 | public: 113 | /** 114 | * Thw two parameters constructor gives users a fast way to build an object 115 | * of this type. 116 | */ 117 | curl_pair(const T option, const curl_header &value) : option(option), value(value) {} 118 | /** 119 | * Simple method that returns the first field of the pair. 120 | */ 121 | inline T first() const NOEXCEPT { 122 | return this->option; 123 | } 124 | /** 125 | * Simple method that returns the second field of the pair as a C struct 126 | * curl_slist pointer. 127 | */ 128 | inline const curl_slist *second() const NOEXCEPT { 129 | return (this->value).get(); 130 | } 131 | private: 132 | const T option; 133 | const curl_header &value; 134 | }; 135 | 136 | } 137 | 138 | #endif /* defined(CURLCPP_CURL_HEADER_H) */ 139 | -------------------------------------------------------------------------------- /include/curl_info.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_info.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_INFO_H 27 | #define CURLCPP_CURL_INFO_H 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "curl_config.h" 34 | 35 | namespace curl { 36 | 37 | /** 38 | * This class represents a structure that provides information about various 39 | * features in the running version of libcurl. 40 | */ 41 | class curl_info { 42 | public: 43 | /** 44 | * The default constructor uses the current version of libcurl 45 | * as referral. 46 | */ 47 | curl_info(); 48 | /** 49 | * Overloaded constructor that allows users to specify the 50 | * libcurl version. 51 | */ 52 | explicit curl_info(CURLversion); 53 | /** 54 | * Returns a string that shows what host information that this 55 | * libcurl was built for. 56 | */ 57 | std::string get_host() const NOEXCEPT; 58 | /** 59 | * Returns a string for the OpenSSL version used. If libcurl has no 60 | * SSL support, the method returns null. 61 | */ 62 | std::string get_ssl_version() const NOEXCEPT; 63 | /** 64 | * Returns a string for libz compression library version. If libcurl 65 | * has no libz support, the method returns null. 66 | */ 67 | std::string get_libz_version() const NOEXCEPT; 68 | /** 69 | * No description supplied for this method. 70 | */ 71 | std::string get_ares() const NOEXCEPT; 72 | /** 73 | * No description supplied for this method. 74 | */ 75 | std::string get_libidn() const NOEXCEPT; 76 | /** 77 | * Returns a string for libssh library version. If libcurl 78 | * has no libssh support, the method returns null. 79 | */ 80 | std::string get_libssh_version() const NOEXCEPT; 81 | /** 82 | * Returns the version number. 83 | */ 84 | unsigned int get_version_number() const NOEXCEPT; 85 | /** 86 | * Check online documentation for the possible return values. 87 | */ 88 | int get_features() const NOEXCEPT; 89 | /** 90 | * No description supplied for this method. 91 | */ 92 | int get_ares_number() const NOEXCEPT; 93 | /** 94 | * No description supplied for this method. 95 | */ 96 | int get_iconv_version_number() const NOEXCEPT; 97 | /** 98 | * Returns the libssl version number. 99 | */ 100 | long get_ssl_version_number() const NOEXCEPT; 101 | /** 102 | * Returns a list of all the protocols supported in the 103 | * running version of libcurl library. 104 | */ 105 | std::list get_protocols() const NOEXCEPT; 106 | private: 107 | const curl_version_info_data *version; 108 | }; 109 | 110 | // Implementation of get_host method. 111 | inline std::string curl_info::get_host() const NOEXCEPT { 112 | return std::string(this->version->host); 113 | } 114 | 115 | // Implementation of get_ssl_version. 116 | inline std::string curl_info::get_ssl_version() const NOEXCEPT { 117 | if (this->version->ssl_version == nullptr) { 118 | return std::string(""); 119 | } 120 | return std::string(this->version->ssl_version); 121 | } 122 | 123 | // Implementation of get_libz_version. 124 | inline std::string curl_info::get_libz_version() const NOEXCEPT { 125 | return std::string(this->version->libz_version); 126 | } 127 | 128 | // Implementation of get_ares method. 129 | inline std::string curl_info::get_ares() const NOEXCEPT { 130 | return std::string(this->version->ares); 131 | } 132 | 133 | // Implementation of get_libidin method. 134 | inline std::string curl_info::get_libidn() const NOEXCEPT { 135 | return std::string(this->version->libidn); 136 | } 137 | 138 | // Implementation of get_libssh_version method. 139 | inline std::string curl_info::get_libssh_version() const NOEXCEPT { 140 | return std::string(this->version->libssh_version); 141 | } 142 | 143 | // Implementation of get_version_number method. 144 | inline unsigned int curl_info::get_version_number() const NOEXCEPT { 145 | return this->version->version_num; 146 | } 147 | 148 | // Implementation of get_features method. 149 | inline int curl_info::get_features() const NOEXCEPT { 150 | return this->version->features; 151 | } 152 | 153 | // Implementation of get_ares_number method. 154 | inline int curl_info::get_ares_number() const NOEXCEPT { 155 | return this->version->ares_num; 156 | } 157 | 158 | // Implementation of get_iconv_version_number method. 159 | inline int curl_info::get_iconv_version_number() const NOEXCEPT { 160 | return this->version->iconv_ver_num; 161 | } 162 | 163 | // Implementation of get_ssl_version_number method. 164 | inline long curl_info::get_ssl_version_number() const NOEXCEPT { 165 | return this->version->ssl_version_num; 166 | } 167 | } 168 | 169 | #endif /* defined(CURLCPP_CURL_INFO_H) */ 170 | -------------------------------------------------------------------------------- /include/curl_interface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_interface.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_INTERFACE_H 27 | #define CURLCPP_CURL_INTERFACE_H 28 | 29 | #include 30 | #include "curl_exception.h" 31 | 32 | namespace curl { 33 | /** 34 | * This class is a common interface for all the libcurl interfaces: 35 | * easy, multi and share. It provides methods that these three interfaces 36 | * have in common with each other. 37 | */ 38 | template class curl_interface { 39 | protected: 40 | /** 41 | * The default constructor will initialize the curl 42 | * environment with the default flag. 43 | */ 44 | curl_interface(); 45 | /** 46 | * Overloaded constructor that initializes curl environment 47 | * with user specified flag. 48 | */ 49 | explicit curl_interface(long); 50 | /** 51 | * The virtual destructor will provide an easy and clean 52 | * way to deallocate resources, closing curl environment 53 | * correctly. 54 | */ 55 | virtual ~curl_interface(); 56 | 57 | private: 58 | /** 59 | * This struct is used for initializing curl only once 60 | * it is implemented as a singleton pattern 61 | */ 62 | struct global_initializer { 63 | explicit global_initializer(long); 64 | ~global_initializer(); 65 | }; 66 | 67 | /** 68 | * the singleton initialization, constructing a global_initializer. 69 | */ 70 | static void init(long flag); 71 | }; 72 | 73 | // Implementation of constructor. 74 | template curl_interface::curl_interface() { 75 | init(CURL_GLOBAL_ALL); 76 | } 77 | 78 | // Implementation of overloaded constructor. 79 | template curl_interface::curl_interface(const long flag) { 80 | init(flag); 81 | } 82 | 83 | // Implementation of the virtual destructor. 84 | template curl_interface::~curl_interface() = default; 85 | 86 | // Implementation of the static initialization function 87 | template void curl_interface::init(const long flag) { 88 | static global_initializer _instance {flag}; 89 | } 90 | 91 | // Implementation of the singleton initializer 92 | template curl_interface::global_initializer::global_initializer(const long flag) { 93 | const CURLcode code = curl_global_init(flag); 94 | if (code != CURLE_OK) { 95 | throw curl_easy_exception(code,__FUNCTION__); 96 | } 97 | } 98 | 99 | // Implementation of the singleton destructor 100 | template curl_interface::global_initializer::~global_initializer() { 101 | curl_global_cleanup(); 102 | } 103 | } 104 | 105 | #endif /* defined(CURLCPP_CURL_INTERFACE_H) */ 106 | -------------------------------------------------------------------------------- /include/curl_ios.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_ios.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_IOS_H 27 | #define CURLCPP_CURL_IOS_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | // Let's typedef this big boy to enhance code readability. 35 | using curlcpp_callback_type = size_t(*)(void *,size_t,size_t,void *); 36 | 37 | namespace { 38 | // Template function for write in memory/variable. 39 | template size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { 40 | const size_t realsize = size*nmemb; 41 | T *const stream = static_cast(userp); 42 | stream->write(static_cast(contents),realsize); 43 | return realsize; 44 | } 45 | 46 | // Default in-memory read callback. 47 | size_t read_memory_callback(void *contents, size_t size, size_t nmemb, void *userp) { 48 | const size_t realsize = size * nmemb; 49 | auto* const mem = static_cast(userp); 50 | mem->read(static_cast(contents), realsize); 51 | return static_cast(mem->gcount()); 52 | } 53 | } 54 | 55 | namespace curl { 56 | // Base class for curl_ios 57 | template class curl_ios { 58 | public: 59 | // This constructor allows to specifiy a custom stream and a custom callback pointer. 60 | curl_ios(T *stream, curlcpp_callback_type callback_ptr) : _stream(stream) { 61 | this->set_callback(callback_ptr); 62 | } 63 | 64 | // This method allow to specify a custom callback pointer. 65 | void set_callback(curlcpp_callback_type callback_ptr) { 66 | _callback_ptr = callback_ptr == nullptr ? write_callback : callback_ptr; 67 | } 68 | 69 | // This method returns the stream pointer. 70 | T *get_stream() const { 71 | return _stream; 72 | } 73 | 74 | // This method return the callback function pointer. 75 | curlcpp_callback_type get_function() const { 76 | return _callback_ptr; 77 | } 78 | private: 79 | // Callback pointer. 80 | curlcpp_callback_type _callback_ptr; 81 | 82 | // Generic stream pointer. 83 | T* _stream; 84 | }; 85 | 86 | 87 | // Template specialization for fstream 88 | template<> class curl_ios { 89 | public: 90 | // This constructor will initialize the stream with a customized stream and a default 91 | // in-memory write callback. 92 | explicit curl_ios(std::fstream &fstream) : _callback_ptr(write_callback) { 93 | this->set_stream(fstream); 94 | } 95 | 96 | // This constructor will initialize the stream with a custom stream and the callback with a customized one. 97 | curl_ios(std::fstream &fstream, curlcpp_callback_type callback_ptr) { 98 | this->set_callback(callback_ptr)->set_stream(fstream); 99 | } 100 | 101 | // This method allow to specify a custom callback pointer. 102 | curl_ios *set_callback(curlcpp_callback_type callback_ptr) { 103 | _callback_ptr = callback_ptr == nullptr ? write_callback : callback_ptr; 104 | return this; 105 | } 106 | 107 | // This method returns the stream pointer. 108 | std::fstream *get_stream() const { 109 | return this->_fstream; 110 | } 111 | 112 | // This method returns the callback for this curl_ios. 113 | curlcpp_callback_type get_function() const { 114 | return this->_callback_ptr; 115 | } 116 | protected: 117 | // This utility method allows to specify and validate a custom stream 118 | curl_ios *set_stream(std::fstream &fstream) { 119 | if (!fstream.is_open()) { 120 | throw std::runtime_error("The file specified is closed!"); 121 | } 122 | _fstream = &fstream; 123 | return this; 124 | } 125 | private: 126 | // Callback pointer. 127 | curlcpp_callback_type _callback_ptr; 128 | 129 | // Generic stream pointer. 130 | std::fstream *_fstream; 131 | }; 132 | 133 | // Template specialization for ostream class. 134 | template<> class curl_ios { 135 | public: 136 | // This constructor will initialize the stream with cout and the callback with a 137 | // default in-memory write callback. 138 | curl_ios() : _callback_ptr(write_callback), _io_stream(&std::cout) {} 139 | 140 | // This constructor will initialize the stream with a customized stream and a 141 | // default in-memory write callback. 142 | explicit curl_ios(std::ostream &io_stream) : 143 | _callback_ptr(write_callback), _io_stream(&io_stream) {} 144 | 145 | // This constructor will initialize the stream with cout and a customized write callback. 146 | explicit curl_ios(curlcpp_callback_type callback_ptr) : _io_stream(&std::cout) { 147 | this->set_callback(callback_ptr); 148 | } 149 | 150 | // This constructor will initialize the stream with a custom stream and the 151 | // callback with a customized one. 152 | curl_ios(std::ostream &io_stream, curlcpp_callback_type callback_ptr) : _io_stream(&io_stream) { 153 | this->set_callback(callback_ptr); 154 | } 155 | 156 | // This method allow to specify a custom callback pointer. 157 | void set_callback(curlcpp_callback_type callback_ptr) { 158 | _callback_ptr = callback_ptr == nullptr ? write_callback : callback_ptr; 159 | } 160 | 161 | // This method returns the stream pointer. 162 | std::ostream *get_stream() const { 163 | return this->_io_stream; 164 | } 165 | 166 | // This method returns the callback for this curl_ios. 167 | curlcpp_callback_type get_function() const { 168 | return this->_callback_ptr; 169 | } 170 | private: 171 | // The callback pointer. 172 | curlcpp_callback_type _callback_ptr; 173 | 174 | // A stream pointer. 175 | std::ostream *_io_stream; 176 | }; 177 | 178 | 179 | // Template specialization for stringstream class. 180 | template<> class curl_ios { 181 | public: 182 | //This constructor allows to specify a custom stringstream stream. 183 | explicit curl_ios(std::stringstream &o_stream) : 184 | _callback_ptr(write_callback), _o_stream(&o_stream) {} 185 | 186 | //This constructor allows to specify a custom stream and a custom callback pointer. 187 | curl_ios(std::stringstream &o_stream, curlcpp_callback_type callback_ptr) { 188 | _o_stream = &o_stream; 189 | this->set_callback(callback_ptr); 190 | } 191 | 192 | // This method allows to specify a custom callback pointer. 193 | void set_callback(curlcpp_callback_type callback_ptr) { 194 | _callback_ptr = callback_ptr == nullptr ? write_callback : callback_ptr; 195 | } 196 | 197 | // This method returns the stream pointer. 198 | std::stringstream *get_stream() const { 199 | return this->_o_stream; 200 | } 201 | 202 | // This method returns the callback pointer. 203 | curlcpp_callback_type get_function() const { 204 | return this->_callback_ptr; 205 | } 206 | private: 207 | // The callback pointer. 208 | curlcpp_callback_type _callback_ptr; 209 | 210 | // The ostringstream pointer. 211 | std::stringstream *_o_stream; 212 | }; 213 | 214 | 215 | // Template specialization for ostringstream class. 216 | template<> class curl_ios { 217 | public: 218 | // This constructor allows to specify a custom ostringstream stream. 219 | explicit curl_ios(std::ostringstream &o_stream) : 220 | _callback_ptr(write_callback), _o_stream(&o_stream) {} 221 | 222 | // This constructor allows to specify a custom stream and a custom callback pointer. 223 | curl_ios(std::ostringstream &o_stream, curlcpp_callback_type callback_ptr) { 224 | _o_stream = &o_stream; 225 | this->set_callback(callback_ptr); 226 | } 227 | 228 | // This method allows to specify a custom callback pointer. 229 | void set_callback(curlcpp_callback_type callback_ptr) { 230 | _callback_ptr = callback_ptr == nullptr ? write_callback : callback_ptr; 231 | } 232 | 233 | // This method returns the stream pointer. 234 | std::ostringstream *get_stream() const { 235 | return this->_o_stream; 236 | } 237 | 238 | // This method returns the callback pointer. 239 | curlcpp_callback_type get_function() const { 240 | return this->_callback_ptr; 241 | } 242 | private: 243 | // The callback pointer. 244 | curlcpp_callback_type _callback_ptr; 245 | 246 | // The ostringstream pointer. 247 | std::ostringstream *_o_stream; 248 | }; 249 | 250 | 251 | // Template specialization for istream class. 252 | template<> class curl_ios { 253 | public: 254 | // The default constructor will initialize the callback pointer and the stream with default values. 255 | curl_ios() : _callback_ptr(read_memory_callback), _istream(&std::cin) {} 256 | 257 | // This constructor allows to specify an input stream while the default callback pointer will be used. 258 | explicit curl_ios(std::istream &istream) : _callback_ptr(read_memory_callback) { 259 | _istream = &istream; 260 | } 261 | 262 | // This overloaded constructor allows to specify a custom callback pointer while the stream will be cin. 263 | explicit curl_ios(curlcpp_callback_type callback_ptr) : _istream(&std::cin) { 264 | this->set_callback(callback_ptr); 265 | } 266 | 267 | // This method allows to specify a custom stream and a custom callback pointer. 268 | curl_ios(std::istream &i_stream, curlcpp_callback_type callback_ptr) : _istream(&i_stream) { 269 | this->set_callback(callback_ptr); 270 | } 271 | 272 | // This method allows to specify a custom callback pointer. 273 | void set_callback(curlcpp_callback_type callback_ptr) { 274 | _callback_ptr = callback_ptr == nullptr ? write_callback : callback_ptr; 275 | } 276 | 277 | // This method returns the stream pointer. 278 | std::istream *get_stream() const { 279 | return _istream; 280 | } 281 | 282 | // This method returns the callback pointer. 283 | curlcpp_callback_type get_function() const { 284 | return _callback_ptr; 285 | } 286 | private: 287 | // The callback pointer. 288 | curlcpp_callback_type _callback_ptr; 289 | 290 | // The stream pointer. 291 | std::istream *_istream; 292 | }; 293 | } 294 | 295 | #endif /* CURLCPP_CURL_IOS_H */ 296 | -------------------------------------------------------------------------------- /include/curl_multi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_multi.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_MULTI_H 27 | #define CURLCPP_CURL_MULTI_H 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "curl_easy.h" 34 | 35 | #define CURLCPP_DEFINE_MOPTION(opt, value_type)\ 36 | template <> struct moption_t {\ 37 | using type = value_type;\ 38 | } 39 | 40 | namespace curl { 41 | namespace detail { 42 | template 43 | struct moption_t; 44 | 45 | template 46 | using MOption_type = typename moption_t::type; 47 | 48 | /* 49 | * If a pipelined connection is currently processing a chunked 50 | * (Transfer-encoding: chunked) request with a current chunk length 51 | * larger than CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, that pipeline will 52 | * not be considered for additional requests. 53 | */ 54 | CURLCPP_DEFINE_MOPTION(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, long); 55 | 56 | /* 57 | * If a pipelined connection is currently processing a request with a 58 | * Content-Length larger than this 59 | * CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, that pipeline will then not be 60 | * considered for additional requests. 61 | */ 62 | CURLCPP_DEFINE_MOPTION(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, long); 63 | 64 | /* 65 | * The set number will be used as the maximum amount of simultaneously 66 | * open connections that libcurl may keep in its connection cache after 67 | * completed use. By default libcurl will enlarge the size for each 68 | * added easy handle to make it fit 4 times the number of added easy 69 | * handles. 70 | */ 71 | CURLCPP_DEFINE_MOPTION(CURLMOPT_MAXCONNECTS, long); 72 | 73 | /* 74 | * The set number will be used as the maximum amount of simultaneously 75 | * open connections to a single host (a host being the same as a host 76 | * name + port number pair). For each new session to a host, libcurl 77 | * will open a new connection up to the limit set by 78 | * CURLMOPT_MAX_HOST_CONNECTIONS. 79 | */ 80 | CURLCPP_DEFINE_MOPTION(CURLMOPT_MAX_HOST_CONNECTIONS, long); 81 | 82 | /* 83 | * The set max number will be used as the maximum amount of outstanding 84 | * requests in a pipelined connection. Only used if pipelining is 85 | * enabled. 86 | */ 87 | CURLCPP_DEFINE_MOPTION(CURLMOPT_MAX_PIPELINE_LENGTH, long); 88 | 89 | /* 90 | * Pass a long for the amount. The set number will be used as the 91 | * maximum number of simultaneously open connections in total using 92 | * this multi handle. 93 | */ 94 | CURLCPP_DEFINE_MOPTION(CURLMOPT_MAX_TOTAL_CONNECTIONS, long); 95 | 96 | /* 97 | * Set the bits parameter to 1 to make libcurl use HTTP pipelining for 98 | * HTTP/1.1 transfers done using this multi handle, as far as possible. 99 | * This means that if you add a second request that can use an already 100 | * existing connection, the second request will be "piped" on the same 101 | * connection rather than being executed in parallel. 102 | */ 103 | CURLCPP_DEFINE_MOPTION(CURLMOPT_PIPELINING, long); 104 | 105 | /* 106 | * Pass a servers array of char *, ending with a NULL entry. This is a 107 | * list of server types prefixes (in the Server: HTTP header) that are 108 | * blacklisted from pipelining, i.e server types that are known to not 109 | * support HTTP pipelining. The array is copied by libcurl. 110 | * 111 | * Note that the comparison matches if the Server: header begins with 112 | * the string in the blacklist, i.e "Server: Ninja 1.2.3" and "Server: 113 | * Ninja 1.4.0" can both be blacklisted by having "Ninja" in the 114 | * backlist. 115 | * 116 | * Pass a NULL pointer to clear the blacklist. 117 | */ 118 | CURLCPP_DEFINE_MOPTION(CURLMOPT_PIPELINING_SERVER_BL, char**); 119 | 120 | /* 121 | * Pass a hosts array of char *, ending with a NULL entry. This is a 122 | * list of sites that are blacklisted from pipelining, i.e sites that 123 | * are known to not support HTTP pipelining. The array is copied by 124 | * libcurl. 125 | * 126 | * Pass a NULL pointer to clear the blacklist. 127 | */ 128 | CURLCPP_DEFINE_MOPTION(CURLMOPT_PIPELINING_SITE_BL, char**); 129 | 130 | /* 131 | * A data pointer to pass to the socket callback set with the 132 | * CURLMOPT_SOCKETFUNCTION option. 133 | */ 134 | CURLCPP_DEFINE_MOPTION(CURLMOPT_SOCKETDATA, void*); 135 | 136 | /* 137 | * The callback gets status updates with changes since the previous 138 | * time the callback was called. See curl_multi_socket_action for more 139 | * details on how the callback is used and should work. 140 | */ 141 | CURLCPP_DEFINE_MOPTION(CURLMOPT_SOCKETFUNCTION, int(*)(CURL* easy, curl_socket_t socket, int action, void* userp, void* socketp)); 142 | 143 | /* 144 | * A data pointer to pass to the timer callback set with the 145 | * CURLMOPT_TIMERFUNCTION option. 146 | */ 147 | CURLCPP_DEFINE_MOPTION(CURLMOPT_TIMERDATA, void*); 148 | 149 | /* 150 | * Your callback function timer_callback should install a non-repeating 151 | * timer with an interval of timeout_ms. 152 | */ 153 | CURLCPP_DEFINE_MOPTION(CURLMOPT_TIMERFUNCTION, int(*)(CURLM* multi, long timeout_ms, void* userp)); 154 | } 155 | 156 | /** 157 | * As libcurl documentation says, the multi interface offers several abilities that 158 | * the easy interface doesn't. They are mainly: 159 | * 1. Enable a "pull" interface. The application that uses libcurl decides where and 160 | * when to ask libcurl to get/send data. 161 | * 2. Enable multiple simultaneous transfers in the same thread without making it 162 | * complicated for the application. 163 | * 3. Enable the application to wait for action on its own file descriptors and curl's 164 | * file descriptors simultaneous easily. 165 | */ 166 | class curl_multi : public curl_interface { 167 | public: 168 | /** 169 | * The multi interface gives users the opportunity to get information about 170 | * transfers. This information is wrapped in the following class. In this 171 | * way users can access this information in an easy and efficient way. 172 | * This class is nested because these messages are only sent when using the 173 | * multi interface. 174 | */ 175 | class curl_message { 176 | public: 177 | /** 178 | * The attributes will be initialized with constructors parameters. With 179 | * this constructor we provide a fast way to build this kind of object. 180 | */ 181 | explicit curl_message(const CURLMsg *, const curl_easy *); 182 | /** 183 | * Inline getter method used to return 184 | * the message for a single handler. 185 | */ 186 | CURLMSG get_message() const; 187 | /** 188 | * Inline getter method used to return 189 | * the code for a single handler. 190 | */ 191 | CURLcode get_code() const; 192 | /** 193 | * Inline getter method used to return 194 | * other data. 195 | */ 196 | const void *get_other() const; 197 | /** 198 | * Returns the handler to the easy interface. 199 | */ 200 | const curl_easy *get_handler() const; 201 | private: 202 | const CURLMSG message; 203 | const void *whatever; 204 | const CURLcode code; 205 | const curl_easy *handler; 206 | }; 207 | 208 | /** 209 | * Simple default constructor. It is used to give a 210 | * default value to all the attributes and provide a 211 | * fast way to create an object of this type. It also 212 | * initializes the curl environment with the default 213 | * values. 214 | */ 215 | curl_multi(); 216 | /** 217 | * Overloaded constructor. Gives users the opportunity 218 | * to initialize the entire curl environment using custom 219 | * options. 220 | */ 221 | explicit curl_multi(long globalOptions); 222 | /** 223 | * Move constructor which moves internal data to another object. 224 | */ 225 | curl_multi(curl_multi&&) NOEXCEPT; 226 | /** 227 | * Move assignment operator which moves internal data to another object. 228 | */ 229 | curl_multi& operator=(curl_multi&&) NOEXCEPT; 230 | /** 231 | * Destructor to deallocate all the resources using 232 | * libcurl. 233 | */ 234 | ~curl_multi() NOEXCEPT override; 235 | /** 236 | * This method allows users to add an option to the multi 237 | * handler, using an object of curl_pair type. 238 | */ 239 | template void add(const curl_pair &); 240 | /** 241 | * Allows users to specify a list of options for the current 242 | * easy handler. In this way, you can specify any iterable data 243 | * structure. 244 | */ 245 | template void add(Iterator, Iterator); 246 | 247 | /** 248 | * Allows users to specify an option for the current multi handler, 249 | * specify an option statically and enforce its corresponding type. 250 | */ 251 | template void add(detail::MOption_type); 252 | 253 | /** 254 | * Overloaded add method. Allows users to specify an easy handler 255 | * to add to the multi handler, to perform more transfers at the same 256 | * time. 257 | */ 258 | void add(const curl_easy &); 259 | 260 | /** 261 | * Overloaded add method. Allows users to specify a vector of easy handlers 262 | * to be added to the multi interface. 263 | */ 264 | void add(const std::vector &); 265 | 266 | /** 267 | * This method removes an easy handler from the multi handler. 268 | */ 269 | void remove(const curl_easy &); 270 | /** 271 | * This method returs the next finished curl_easy (if there is), 272 | * otherwise nullptr is returned 273 | */ 274 | std::unique_ptr get_next_finished(); 275 | /** 276 | * Perform all the operations. Go baby! If the performing operations 277 | * have finished, the method returns true. Else, returns false. Check 278 | * online documentation for further documentation. 279 | */ 280 | bool perform(); 281 | /** 282 | * This method wraps the libcurl function that reads/writes available data 283 | * given an action. Read the libcurl online documentation to learn more 284 | * about this function! 285 | */ 286 | bool socket_action(curl_socket_t, int); 287 | /** 288 | * This method wraps the libcurl function that extracts file descriptor 289 | * information from the multi handler. 290 | * Read the libcurl online documentation to learn more about this function. 291 | */ 292 | void set_descriptors(fd_set *, fd_set *, fd_set *, int *); 293 | /** 294 | * This function polls on all file descriptors used by the curl easy handles 295 | * contained in the given multi handle set. 296 | */ 297 | void wait(struct curl_waitfd [], unsigned int, int, int *); 298 | /** 299 | * This function creates an association in the multi handle between the given 300 | * socket and a private pointer of the application. 301 | */ 302 | void assign(curl_socket_t, void *); 303 | /** 304 | * If you are using the libcurl multi interface you should call this method 305 | * to figure out how long your application should wait for socket actions 306 | * - at most - before proceeding. 307 | */ 308 | void timeout(long *); 309 | /** 310 | * Inline getter method used to return the currently active transfers. 311 | */ 312 | int get_active_transfers() const NOEXCEPT; 313 | /** 314 | * Inline getter method used to return the currently queued messages. 315 | */ 316 | int get_message_queued() const NOEXCEPT; 317 | 318 | /** 319 | * Simple getter method used to return the multi handle. 320 | */ 321 | CURLM *get_curl() const; 322 | private: 323 | struct multi_deleter { 324 | void operator()(CURLM* ptr) const; 325 | }; 326 | 327 | using multi_ptr = std::unique_ptr; 328 | 329 | multi_ptr curl; 330 | int active_transfers; 331 | int message_queued; 332 | std::unordered_map handles; 333 | }; 334 | 335 | // Implementation of add method 336 | template void curl_multi::add(const curl_pair &pair) { 337 | const CURLMcode code = curl_multi_setopt(this->curl.get(),pair.first(),pair.second()); 338 | if (code != CURLM_OK) { 339 | throw curl_multi_exception(code,__FUNCTION__); 340 | } 341 | } 342 | 343 | // Implementation of overloaded add method. 344 | template void curl_multi::add(Iterator begin, const Iterator end) { 345 | for (; begin != end; ++begin) { 346 | this->add(*begin); 347 | } 348 | } 349 | 350 | // Implementation of overloaded add method. 351 | template void curl_multi::add(detail::MOption_type val) { 352 | const auto code = curl_multi_setopt(this->curl.get(), Opt, val); 353 | if (code != CURLM_OK) { 354 | throw curl_multi_exception(code, __FUNCTION__); 355 | } 356 | } 357 | 358 | // Implementation of get_active_transfers method. 359 | inline int curl_multi::get_active_transfers() const NOEXCEPT { 360 | return this->active_transfers; 361 | } 362 | 363 | // Implementation of get_message_queued method. 364 | inline int curl_multi::get_message_queued() const NOEXCEPT { 365 | return this->message_queued; 366 | } 367 | 368 | // Implementation of curl_message get_message method. 369 | inline CURLMSG curl_multi::curl_message::get_message() const { 370 | return this->message; 371 | } 372 | 373 | // Implementation of curl_message get_code method. 374 | inline CURLcode curl_multi::curl_message::get_code() const { 375 | return this->code; 376 | } 377 | 378 | // Implementation of curl_message get_other method. 379 | inline const void *curl_multi::curl_message::get_other() const { 380 | return this->whatever; 381 | } 382 | 383 | // Implementation of curl_message get_handler method. 384 | inline const curl_easy *curl_multi::curl_message::get_handler() const { 385 | return this->handler; 386 | } 387 | } 388 | 389 | #undef CURLCPP_DEFINE_MOPTION 390 | #endif /* defined(CURLCPP_CURL_MULTI_H) */ 391 | -------------------------------------------------------------------------------- /include/curl_option.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 - Qiangqiang Wu 5 | * File - curl_option.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_OPTION_H 27 | #define CURLCPP_CURL_OPTION_H 28 | 29 | #include 30 | #include 31 | #include "curl_pair.h" 32 | 33 | namespace curl { 34 | template 35 | inline curl_pair 36 | make_option(const CURLoption opt, const V &val) 37 | { 38 | return curl_pair(opt, val); 39 | } 40 | 41 | template 42 | inline curl_pair 43 | make_formoption(const CURLformoption opt, const V &val) 44 | { 45 | return curl_pair(opt, val); 46 | } 47 | } // of namespace curl 48 | 49 | #endif /* defined(CURLCPP_CURL_OPTION_H) */ 50 | -------------------------------------------------------------------------------- /include/curl_pair.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_pair.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_PAIR_H 27 | #define CURLCPP_CURL_PAIR_H 28 | 29 | #include 30 | #include "curl_config.h" 31 | 32 | namespace curl { 33 | 34 | // Forward reference to curl_form and curl_header 35 | class curl_form; 36 | class curl_header; 37 | 38 | /** 39 | * This is a class that wraps two objects: an option and the value for 40 | * that option. It's very useful when building forms or setting options 41 | * for easy/multi/share handlers. It let you specify the libcurl option 42 | * and its value. 43 | */ 44 | template class curl_pair { 45 | public: 46 | /** 47 | * The two parameters constructor gives users a fast way to 48 | * build an object of this type. 49 | */ 50 | curl_pair(const T option, const K &value) : option(option), value(value) {}; 51 | /** 52 | * Simple method that returns the first field of the pair. 53 | */ 54 | inline T first() const NOEXCEPT { 55 | return this->option; 56 | } 57 | /** 58 | * Simple method that returns the second field of the pair. 59 | */ 60 | inline K second() const NOEXCEPT { 61 | return this->value; 62 | } 63 | private: 64 | const T option; 65 | const K &value; 66 | }; 67 | 68 | /** 69 | * Template specialization for C++ strings and CURLformoption. 70 | */ 71 | template<> class curl_pair { 72 | public: 73 | /** 74 | * The two parameters constructor gives users a fast way to 75 | * build an object of this type. 76 | */ 77 | curl_pair(const CURLformoption option, const std::string &value) : option(option), value(value.c_str()) {} 78 | /** 79 | * Alternate constructor that handles string constants without 80 | * referencing temporary objects. 81 | */ 82 | curl_pair(const CURLformoption option, const char *value) : option(option), value(value) {} 83 | /** 84 | * Simple method that returns the first field of the pair. 85 | */ 86 | inline CURLformoption first() const NOEXCEPT { 87 | return this->option; 88 | } 89 | /** 90 | * Simple method that returns the second field of the pair as 91 | * a C string, so a const char *. 92 | */ 93 | inline const char *second() const NOEXCEPT { 94 | return this->value; 95 | } 96 | private: 97 | const CURLformoption option; 98 | const char* value; 99 | }; 100 | 101 | /** 102 | * Template specialization for C++ strings. Why do we need this? Because 103 | * curl_pair must be passed to C functions that doesen't know how to 104 | * handle C++ string type, so we can specialize curl_pair class in a 105 | * manner that its methods returns a const char *. 106 | */ 107 | template class curl_pair { 108 | public: 109 | /** 110 | * The two parameters constructor gives users a fast way to 111 | * build an object of this type. 112 | */ 113 | curl_pair(const T option, const std::string &value) : 114 | option(option == CURLOPT_POSTFIELDS ? CURLOPT_COPYPOSTFIELDS : option), value(value) {}; 115 | /** 116 | * Simple method that returns the first field of the pair. 117 | */ 118 | inline T first() const NOEXCEPT { 119 | return this->option; 120 | } 121 | /** 122 | * Simple method that returns the second field of the pair as 123 | * a C string, so a const char *. 124 | */ 125 | inline const char *second() const NOEXCEPT { 126 | return this->value.c_str(); 127 | } 128 | private: 129 | const T option; 130 | const std::string &value; 131 | }; 132 | 133 | /** 134 | * Template specialization for curl_form type. Why do we need this? Because 135 | * curl_form wraps a struct curl_httppost list. libcurl functions can't handle 136 | * curl_form type, so we need to specialize curl_pair to return a struct 137 | * curl_httppost *. 138 | * Definition at curl_form.h 139 | */ 140 | template class curl_pair; 141 | 142 | /** 143 | * Template specialization for curl_header type. Why do we need this? Because 144 | * curl_header wraps a struct curl_slist list of headers. libcurl functions can't 145 | * handle a curl_header type, so we need to specialize curl_pair to return a 146 | * struct curl_slist *. 147 | * Definition at curl_header.h 148 | */ 149 | template class curl_pair; 150 | } 151 | 152 | #endif /* defined(CURLCPP_CURL_PAIR_H) */ 153 | -------------------------------------------------------------------------------- /include/curl_receiver.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_receiver.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_RECEIVER_H 27 | #define CURLCPP_CURL_RECEIVER_H 28 | 29 | #include 30 | #include "curl_easy.h" 31 | 32 | namespace curl { 33 | 34 | /** 35 | * This class implements a receiver that allow users to receive raw 36 | * data on an established connection on an easy handler. 37 | */ 38 | template class curl_receiver { 39 | public: 40 | /** 41 | * The default constructor simply initializes the attributes. In this 42 | * case just the received bytes number is initialized to zero. 43 | */ 44 | curl_receiver(); 45 | /** 46 | * In this case the destructor does not have to release any resource. 47 | */ 48 | ~curl_receiver() = default; 49 | /** 50 | * The receive method wraps curl_easy_recv function and receives raw 51 | * data from the established connection on an easy handler. 52 | */ 53 | bool receive(curl_easy &); 54 | /** 55 | * Simple getter method that returns the buffer with the received 56 | * data. 57 | */ 58 | std::array get_buffer() const; 59 | /** 60 | * Simple getter method that returns the number of received bytes. 61 | * Real applications should check this number to ensure that the 62 | * communication ended without errors. 63 | */ 64 | size_t get_received_bytes() const; 65 | private: 66 | std::array _buffer; 67 | size_t _recv_bytes; 68 | }; 69 | 70 | // Implementation of constructor. 71 | template curl_receiver::curl_receiver() : _recv_bytes(0) { 72 | if (SIZE <= 0) { 73 | throw curl_exception("Buffer size can not be less or equal to zero",__FUNCTION__); 74 | } 75 | } 76 | 77 | // Implementation of receive method. 78 | template bool curl_receiver::receive(curl_easy &easy) { 79 | const CURLcode code = curl_easy_recv(easy.get_curl(),&_buffer,SIZE,&_recv_bytes); 80 | if (code == CURLE_AGAIN) { 81 | return false; 82 | } 83 | if (code != CURLE_OK) { 84 | throw curl_easy_exception(code,__FUNCTION__); 85 | } 86 | return true; 87 | } 88 | 89 | // Implementation of get_buffer method. 90 | template inline std::array curl_receiver::get_buffer() const { 91 | return _buffer; 92 | } 93 | 94 | // Implementation of get_received_buffer method. 95 | template inline size_t curl_receiver::get_received_bytes() const { 96 | return _recv_bytes; 97 | } 98 | } 99 | 100 | #endif /* defined(CURLCPP_CURL_RECEIVER_H) */ 101 | -------------------------------------------------------------------------------- /include/curl_sender.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_sender.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_SENDER_H 27 | #define CURLCPP_CURL_SENDER_H 28 | 29 | #include "curl_easy.h" 30 | 31 | namespace curl { 32 | /** 33 | * This class implements a sender that sends raw data on an established 34 | * connection on an easy handler. 35 | */ 36 | template class curl_sender { 37 | public: 38 | /** 39 | * The constructor initializes the easy handler and the number of 40 | * sent bytes. 41 | */ 42 | explicit curl_sender(curl_easy &easy); 43 | /** 44 | * This method wraps the curl_easy_send function that sends raw data 45 | * on an established connection on an easy handler. 46 | */ 47 | void send(T, size_t); 48 | /** 49 | * Simple getter method that returns sent's current byte number. 50 | */ 51 | size_t get_sent_bytes() const; 52 | private: 53 | curl_easy &_easy; 54 | size_t _sent_bytes; 55 | }; 56 | 57 | // Implementation of constructor. 58 | template curl_sender::curl_sender(curl_easy &easy) : _easy(easy), _sent_bytes(0) { 59 | // ... nothing to do here ... 60 | } 61 | 62 | // Implementation of send method. 63 | template void curl_sender::send(const T buffer, const size_t size) { 64 | const CURLcode code = curl_easy_send(_easy.get_curl(),buffer,size,&_sent_bytes); 65 | if (code != CURLE_OK) { 66 | throw curl_easy_exception(code,__FUNCTION__); 67 | } 68 | } 69 | 70 | // Implementation of get_sent_bytes method. 71 | template inline size_t curl_sender::get_sent_bytes() const { 72 | return _sent_bytes; 73 | } 74 | 75 | /** 76 | * Template specialization for strings. C++ string type is not supported by libcurl C 77 | * functions, so we must treat it as a const char pointer. This is the purpose of 78 | * this class. 79 | */ 80 | template<> class curl_sender { 81 | public: 82 | /** 83 | * The constructor initializes the easy handler and the number of 84 | * sent bytes. 85 | */ 86 | explicit curl_sender(curl_easy &easy) : _easy(easy), _sent_bytes(0) {} 87 | /** 88 | * This method wraps the curl_easy_send function that sends raw data 89 | * on an established connection on an easy handler, treating strings 90 | * as const char pointers. 91 | */ 92 | void send(const std::string& buffer) { 93 | const CURLcode code = curl_easy_send(_easy.get_curl(),buffer.c_str(),buffer.length(),&_sent_bytes); 94 | if (code != CURLE_OK) { 95 | throw curl_easy_exception(code,__FUNCTION__); 96 | } 97 | } 98 | /** 99 | * Simple getter method that returns sent's current byte number. 100 | */ 101 | inline size_t get_sent_bytes() const { 102 | return _sent_bytes; 103 | } 104 | private: 105 | curl_easy &_easy; 106 | size_t _sent_bytes; 107 | }; 108 | } 109 | 110 | #endif /* defined(CURLCPP_CURL_SENDER_H) */ 111 | -------------------------------------------------------------------------------- /include/curl_share.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_share.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_SHARE_H 27 | #define CURLCPP_CURL_SHARE_H 28 | 29 | #include "curl_interface.h" 30 | #include "curl_pair.h" 31 | 32 | #define CURLCPP_DEFINE_SOPTION(opt, value_type)\ 33 | template <> struct shoption_t {\ 34 | using type = value_type;\ 35 | } 36 | 37 | namespace curl { 38 | namespace detail { 39 | template 40 | struct shoption_t; 41 | 42 | template 43 | using SHOption_type = typename shoption_t::type; 44 | 45 | /* 46 | * The parameter must be a pointer to a function matching the following prototype: 47 | * void lock_function(CURL *handle, curl_lock_data data, curl_lock_access access, void *userptr); 48 | * data defines what data libcurl wants to lock, and you must make sure that only one lock is given 49 | * at any time for each kind of data. access defines what access type libcurl wants, shared or single. 50 | * userptr is the pointer you set with CURLSHOPT_USERDATA. 51 | */ 52 | CURLCPP_DEFINE_SOPTION(CURLSHOPT_LOCKFUNC, 53 | void(*)(CURL *handle, curl_lock_data data, curl_lock_access access, void *userptr)); 54 | /* 55 | * The parameter must be a pointer to a function matching the following prototype: 56 | * void unlock_function(CURL *handle, curl_lock_data data, void *userptr); 57 | * data defines what data libcurl wants to unlock, and you must make sure that only one lock is given 58 | * at any time for each kind of data. 59 | * userptr is the pointer you set with CURLSHOPT_USERDATA. 60 | */ 61 | CURLCPP_DEFINE_SOPTION(CURLSHOPT_UNLOCKFUNC, void(*)(CURL *handle, curl_lock_data data, void *userptr)); 62 | 63 | /* 64 | * The parameter specifies a type of data that should be shared. This may be set to one of the values described below. 65 | * CURL_LOCK_DATA_COOKIE: Cookie data will be shared across the easy handles using this shared object. 66 | * CURL_LOCK_DATA_DNS: Cached DNS hosts will be shared across the easy handles using this shared object. 67 | * Note that when you use the multi interface, all easy handles added to the same multi handle will share 68 | * DNS cache by default without this having to be used! 69 | * CURL_LOCK_DATA_SSL_SESSION: SSL session IDs will be shared across the easy handles using this shared 70 | * object. This will reduce the time spent in the SSL handshake when reconnecting to the same server. 71 | * Note SSL session IDs are reused within the same easy handle by default. Note this symbol was added 72 | * in 7.10.3 but was not implemented until 7.23.0. 73 | */ 74 | CURLCPP_DEFINE_SOPTION(CURLSHOPT_SHARE, int); 75 | 76 | /* 77 | * This option does the opposite of CURLSHOPT_SHARE. It specifies that the specified parameter will no longer 78 | * be shared. Valid values are the same as those for CURLSHOPT_SHARE. 79 | */ 80 | CURLCPP_DEFINE_SOPTION(CURLSHOPT_UNSHARE, int); 81 | 82 | /* 83 | * The parameter allows you to specify a pointer to data that will be passed to the lock_function and 84 | * unlock_function each time it is called. 85 | */ 86 | CURLCPP_DEFINE_SOPTION(CURLSHOPT_USERDATA, void *); 87 | } 88 | 89 | /** 90 | * Definition of share interface. The purpose of this interface is to 91 | * enable data sharing between curl handlers. 92 | */ 93 | class curl_share : public curl_interface { 94 | public: 95 | /** 96 | * The default constructor will initialize the share 97 | * handle to its default value. 98 | */ 99 | curl_share(); 100 | /** 101 | * The overloaded constructor allows users to initialize 102 | * the share handle and initialize the libcurl environment 103 | * using customs flags. 104 | */ 105 | explicit curl_share(long); 106 | /** 107 | * Copy constructor to perform the copy of the share handle. 108 | */ 109 | curl_share(const curl_share &); 110 | /** 111 | * Assignment operator to perform assignment between two or 112 | * more objects of this class. 113 | */ 114 | curl_share &operator=(const curl_share &); 115 | /** 116 | * The destructor will free the share handler previously 117 | * allocated. 118 | */ 119 | ~curl_share() NOEXCEPT override; 120 | /** 121 | * Add method used to add options to the share handle. 122 | */ 123 | template void add(detail::SHOption_type); 124 | /** 125 | * Allows users to specify a list of options for the current 126 | * easy handler. In this way, you can specify any iterable data 127 | * structure. 128 | */ 129 | template void add(Iterator, Iterator); 130 | /** 131 | * Simple getter method used to return the underlying shared handle. 132 | */ 133 | CURLSH *get() const; 134 | protected: 135 | void initialize_curl_share(); 136 | private: 137 | CURLSH *curl; 138 | }; 139 | 140 | // Implementation of overloaded constructor. 141 | inline curl_share::curl_share(const long flag) : curl_interface(flag) { 142 | initialize_curl_share(); 143 | } 144 | 145 | // Implementation of copy constructor. 146 | inline curl_share::curl_share(const curl_share &share) : curl_interface() { 147 | (void)share; // unused 148 | initialize_curl_share(); 149 | } 150 | 151 | // Implementation of add method 152 | template void curl_share::add(const detail::SHOption_type val) { 153 | const auto code = curl_share_setopt(this->curl, Opt, val); 154 | if (code != CURLSHE_OK) { 155 | throw curl_share_exception(code, __FUNCTION__); 156 | } 157 | } 158 | 159 | // Implementation of overloaded add method. 160 | template void curl_share::add(Iterator begin, const Iterator end) { 161 | for (; begin != end; ++begin) { 162 | this->add(*begin); 163 | } 164 | } 165 | 166 | // Implementation of underlying share getter method. 167 | inline CURLSH *curl_share::get() const { 168 | return this->curl; 169 | } 170 | } 171 | 172 | #endif /* defined(CURLCPP_CURL_SHARE_H) */ 173 | -------------------------------------------------------------------------------- /include/curl_utility.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2023 - Giuseppe Persico 5 | * File - curl_utility.h 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef CURLCPP_CURL_UTILITY_H 27 | #define CURLCPP_CURL_UTILITY_H 28 | 29 | #include 30 | #include "curl_exception.h" 31 | 32 | namespace curl { 33 | /** 34 | * This class provides some utilities that are unrelated to 35 | * the libcurl interfaces, so they are enclosed in this class. 36 | */ 37 | class curl_utility { 38 | public: 39 | /** 40 | * This method returns the number of seconds since the Epoch, 41 | * January 1st 1970 00:00:00 in the UTC time zone, for the date 42 | * and time that the datestring parameter specifies. Check the 43 | * online documentation for more information about the datetime 44 | * parameter. 45 | */ 46 | static time_t get_date(const std::string&); 47 | private: 48 | /** 49 | * Build an object of this type have no sense. So let's hide 50 | * the constructor. 51 | */ 52 | curl_utility() = default; 53 | }; 54 | 55 | // Implementation of get_date method. 56 | time_t curl_utility::get_date(const std::string& format) { 57 | const time_t value = curl_getdate(format.c_str(),nullptr); 58 | if (value == -1) { 59 | throw curl_exception("*** Error while parsing the date ***",__FUNCTION__); 60 | } 61 | return value; 62 | } 63 | } 64 | 65 | #endif /* defined(CURLCPP_CURL_UTILITY_H) */ 66 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CURLCPP_HEADER_LIST 2 | ../include/cookie.h 3 | ../include/cookie_date.h 4 | ../include/cookie_datetime.h 5 | ../include/cookie_time.h 6 | ../include/curl_config.h 7 | ../include/curl_cookie.h 8 | ../include/curl_easy.h 9 | ../include/curl_easy_info.h 10 | ../include/curl_exception.h 11 | ../include/curl_form.h 12 | ../include/curl_global.h 13 | ../include/curl_header.h 14 | ../include/curl_info.h 15 | ../include/curl_interface.h 16 | ../include/curl_ios.h 17 | ../include/curl_multi.h 18 | ../include/curl_option.h 19 | ../include/curl_pair.h 20 | ../include/curl_receiver.h 21 | ../include/curl_sender.h 22 | ../include/curl_share.h 23 | ../include/curl_utility.h 24 | ) 25 | 26 | 27 | if(NOT BUILD_SHARED_LIBS) 28 | add_library(curlcpp 29 | curl_easy.cpp 30 | curl_header.cpp 31 | curl_global.cpp 32 | curl_form.cpp 33 | curl_multi.cpp 34 | curl_share.cpp 35 | curl_info.cpp 36 | curl_cookie.cpp 37 | curl_exception.cpp 38 | cookie.cpp 39 | cookie_date.cpp 40 | cookie_time.cpp 41 | cookie_datetime.cpp 42 | 43 | ${CURLCPP_HEADER_LIST} 44 | ) 45 | else() 46 | add_library(curlcpp ${BUILD_SHARED_LIBS} 47 | curl_easy.cpp 48 | curl_header.cpp 49 | curl_global.cpp 50 | curl_form.cpp 51 | curl_multi.cpp 52 | curl_share.cpp 53 | curl_info.cpp 54 | curl_cookie.cpp 55 | curl_exception.cpp 56 | cookie.cpp 57 | cookie_date.cpp 58 | cookie_time.cpp 59 | cookie_datetime.cpp 60 | 61 | ${CURLCPP_HEADER_LIST} 62 | ) 63 | endif() 64 | 65 | add_library(curlcpp::curlcpp ALIAS curlcpp) 66 | 67 | target_include_directories(curlcpp PUBLIC 68 | "$" 69 | "$") 70 | 71 | target_compile_features(curlcpp PUBLIC cxx_std_11) 72 | 73 | target_compile_options(curlcpp PRIVATE 74 | $<$:-Wall -Wextra -Wpedantic> 75 | $<$:-Wall -Wpedantic> 76 | $<$:/W4 /wd4244 /wd4305 /wd4996 /wd4267 /wd4018 /wd4706> 77 | ) 78 | 79 | if(CURLCPP_USE_PKGCONFIG) 80 | find_package(PkgConfig REQUIRED) 81 | pkg_check_modules(libcurl REQUIRED IMPORTED_TARGET libcurl>=${CURL_MIN_VERSION}) 82 | target_link_libraries(curlcpp PUBLIC PkgConfig::libcurl) 83 | else() 84 | # Add MacPorts 85 | if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 86 | set(CMAKE_PREFIX_PATH /opt/local ${CMAKE_PREFIX_PATH}) 87 | endif() 88 | 89 | find_package(CURL ${CURL_MIN_VERSION} REQUIRED) 90 | 91 | if(TARGET CURL::libcurl) 92 | target_link_libraries(curlcpp PUBLIC CURL::libcurl) 93 | else() 94 | target_include_directories(curlcpp PUBLIC ${CURL_INCLUDE_DIRS}) 95 | target_link_libraries(curlcpp PUBLIC ${CURL_LIBRARIES}) 96 | endif() 97 | endif() 98 | 99 | if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 100 | target_compile_options(curlcpp PUBLIC -stdlib=libc++) 101 | endif() 102 | 103 | if(IPO_SUPPORTED AND CMAKE_BUILD_TYPE STREQUAL "Release") 104 | set_target_properties(curlcpp PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) 105 | endif() 106 | 107 | set_target_properties (curlcpp PROPERTIES PUBLIC_HEADER "${CURLCPP_HEADER_LIST}") 108 | 109 | include(GNUInstallDirs) 110 | install(TARGETS curlcpp 111 | EXPORT ${PROJECT_NAME}Targets 112 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/ 113 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 114 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 115 | -------------------------------------------------------------------------------- /src/cookie.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: cookie.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "cookie.h" 7 | 8 | using std::string; 9 | 10 | // Implementation of constructor. 11 | curl::cookie::cookie(const string& name, const string& value, 12 | const cookie_datetime &datetime, const string& path, const string& domain, const bool secure) { 13 | 14 | set_name(name)->set_value(value)->set_path(path)->set_domain(domain)->set_secure(secure)->set_datetime(datetime); 15 | } 16 | 17 | // Implementation of overloaded constructor. 18 | curl::cookie::cookie(const char *name, const char * value, const cookie_datetime &datetime, 19 | const char *path, const char *domain, const bool secure) { 20 | 21 | set_name(name)->set_value(value)->set_path(path)->set_domain(domain)->set_secure(secure)->set_datetime(datetime); 22 | } 23 | 24 | // Implementation of set_name method. 25 | curl::cookie *curl::cookie::set_name(const string& _name) { 26 | if (_name.empty()) { 27 | throw curl_easy_exception("Cookie must have a name",__FUNCTION__); 28 | } 29 | this->name = _name; 30 | return this; 31 | } 32 | 33 | // Implementation of set_name overloaded method. 34 | curl::cookie *curl::cookie::set_name(const char *_name) { 35 | if (_name == nullptr) { 36 | throw curl_easy_exception("Cookie must have a name",__FUNCTION__); 37 | } 38 | this->name = string(_name); 39 | return this; 40 | } 41 | 42 | // Implementation of set_name method. 43 | curl::cookie *curl::cookie::set_value(const string& _value) { 44 | this->value = _value; 45 | return this; 46 | } 47 | 48 | // Implementation of set_value method. 49 | curl::cookie *curl::cookie::set_value(const char *_value) { 50 | if (_value == nullptr) { 51 | this->value = ""; 52 | } else { 53 | this->value = string(_value); 54 | } 55 | return this; 56 | } 57 | 58 | // Implementation of set_path method. 59 | curl::cookie *curl::cookie::set_path(const string& _path) NOEXCEPT { 60 | this->path = _path.empty() ? "/" : _path; 61 | return this; 62 | } 63 | 64 | // Implementation of set_path overloaded method. 65 | curl::cookie *curl::cookie::set_path(const char *_path) NOEXCEPT { 66 | if (_path == nullptr) { 67 | this->path = "/"; 68 | } else { 69 | this->path = string(path); 70 | } 71 | return this; 72 | } 73 | 74 | // Implelementation of set_domain method. 75 | curl::cookie *curl::cookie::set_domain(const string& _domain) NOEXCEPT { 76 | this->domain = _domain; 77 | return this; 78 | } 79 | 80 | // Implementation of set_domain overloaded method. 81 | curl::cookie *curl::cookie::set_domain(const char *_domain) NOEXCEPT { 82 | if (_domain == nullptr) { 83 | this->domain = ""; 84 | } else { 85 | this->domain = string(domain); 86 | } 87 | return this; 88 | } 89 | 90 | // Implementation of set_secure method. 91 | curl::cookie *curl::cookie::set_secure(const bool _secure) NOEXCEPT { 92 | this->secure = _secure; 93 | return this; 94 | } 95 | 96 | // Implementation of set_secure overloaded method. 97 | curl::cookie *curl::cookie::set_secure(const string& _secure) NOEXCEPT { 98 | set_secure(_secure == "secure"); 99 | return this; 100 | } 101 | 102 | // Implementation of set_secure overloaded method. 103 | curl::cookie *curl::cookie::set_secure(const char *_secure) NOEXCEPT { 104 | if (_secure == nullptr) { 105 | set_secure(false); 106 | } else { 107 | set_secure(string(_secure)); 108 | } 109 | return this; 110 | } 111 | 112 | // Implementation of set_secure method. 113 | curl::cookie *curl::cookie::set_secure(const unsigned int _secure) { 114 | if (_secure == 0) { 115 | set_secure(false); 116 | } else if (_secure == 1) { 117 | set_secure(true); 118 | } else { 119 | throw curl_easy_exception("The security can be 0 (false) or 1 (true)",__FUNCTION__); 120 | } 121 | return this; 122 | } 123 | 124 | // Implementation of set_datetime method. 125 | curl::cookie *curl::cookie::set_datetime(const cookie_datetime & _datetime) NOEXCEPT { 126 | this->datetime = _datetime; 127 | return this; 128 | } 129 | 130 | // Implementation of get_name method. 131 | string curl::cookie::get_name() const NOEXCEPT { 132 | return this->name; 133 | } 134 | 135 | // Implmentation of get_value method. 136 | string curl::cookie::get_value() const NOEXCEPT { 137 | return this->value; 138 | } 139 | 140 | // Implementation of get_path method. 141 | string curl::cookie::get_path() const NOEXCEPT { 142 | return this->path; 143 | } 144 | 145 | // Implementation of get_domain method. 146 | string curl::cookie::get_domain() const NOEXCEPT { 147 | return this->domain; 148 | } 149 | 150 | // Implementation of is_secure method. 151 | bool curl::cookie::is_secure() const NOEXCEPT { 152 | return this->secure; 153 | } 154 | 155 | // Implementation of get_datetime method. 156 | curl::cookie_datetime curl::cookie::get_datetime() const NOEXCEPT { 157 | return this->datetime; 158 | } 159 | 160 | // Implementation of get_formatted method. 161 | string curl::cookie::get_formatted() NOEXCEPT { 162 | string _secure = this->is_secure() == 1 ? "secure" : ""; 163 | 164 | return "Set-Cookie: "+this->name+"="+this->value+"; expires="+this->datetime.get_formatted() 165 | +"; path="+this->path+"; domain="+this->domain+" "+_secure; 166 | } 167 | -------------------------------------------------------------------------------- /src/cookie_date.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: cookie_date.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "cookie_date.h" 7 | 8 | using std::out_of_range; 9 | using std::ostringstream; 10 | 11 | // Implementation of constructor with parameters. 12 | curl::cookie_date::cookie_date(const unsigned int week_day, const unsigned int day, 13 | const unsigned int month, const unsigned int year) NOEXCEPT { 14 | 15 | this->set_week_day(week_day)->set_day(day)->set_month(month)->set_year(year); 16 | } 17 | 18 | // Implementation of set_week_day method. 19 | curl::cookie_date *curl::cookie_date::set_week_day(const unsigned int weekDay) NOEXCEPT { 20 | try { 21 | this->week_day = details::weekdayNames.at(weekDay); 22 | } catch (const out_of_range &) { 23 | this->week_day = "Mon"; 24 | } 25 | return this; 26 | } 27 | 28 | // Implementation of set_day method. 29 | curl::cookie_date *curl::cookie_date::set_day(const unsigned int cookieDay) NOEXCEPT { 30 | this->day = (cookieDay < 1 or cookieDay > 31) ? 1 : cookieDay; 31 | return this; 32 | } 33 | 34 | // Implementation of set_month method. 35 | curl::cookie_date *curl::cookie_date::set_month(const unsigned int cookieMonth) { 36 | try { 37 | this->month = details::monthsNames.at(cookieMonth); 38 | } catch (const out_of_range &) { 39 | this->month = "Jan"; 40 | } 41 | return this; 42 | } 43 | 44 | // Implementation of set_year method. 45 | curl::cookie_date *curl::cookie_date::set_year(const unsigned int cookieYear) NOEXCEPT { 46 | this->year = (cookieYear < 1970 ) ? 1970 : cookieYear; 47 | return this; 48 | } 49 | 50 | std::string curl::cookie_date::get_week_day() const NOEXCEPT { 51 | return this->week_day; 52 | } 53 | 54 | // Implementation of get_day method. 55 | unsigned int curl::cookie_date::get_day() const NOEXCEPT { 56 | return this->day; 57 | } 58 | 59 | // Implementation of get_month method. 60 | std::string curl::cookie_date::get_month() const NOEXCEPT { 61 | return this->month; 62 | } 63 | 64 | // Implementation of get_year method. 65 | unsigned int curl::cookie_date::get_year() const NOEXCEPT { 66 | return this->year; 67 | } 68 | 69 | // Implementation of get_formatted method. 70 | std::string curl::cookie_date::get_formatted() NOEXCEPT { 71 | ostringstream stream; 72 | stream<week_day<<", "<day<<"-"<month<<"-"<year; 73 | return stream.str(); 74 | } -------------------------------------------------------------------------------- /src/cookie_datetime.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: cookie_datetime.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "cookie_datetime.h" 7 | 8 | // Implementation of constructor with parameters. 9 | curl::cookie_datetime::cookie_datetime(const cookie_time &time, const cookie_date &date) NOEXCEPT { 10 | this->set_time(time)->set_date(date); 11 | } 12 | 13 | // Implementation of set_time method. 14 | curl::cookie_datetime *curl::cookie_datetime::set_time(const cookie_time &cookieTime) NOEXCEPT { 15 | this->time = cookieTime; 16 | return this; 17 | } 18 | 19 | // Implementation of set_date method. 20 | curl::cookie_datetime *curl::cookie_datetime::set_date(const cookie_date &cookieDate) NOEXCEPT { 21 | this->date = cookieDate; 22 | return this; 23 | } 24 | 25 | // Implementation of get_time method. 26 | curl::cookie_time curl::cookie_datetime::get_time() const NOEXCEPT { 27 | return this->time; 28 | } 29 | 30 | // Implementation of get_date method. 31 | curl::cookie_date curl::cookie_datetime::get_date() const NOEXCEPT { 32 | return this->date; 33 | } 34 | 35 | // Implementation of get method. 36 | std::string curl::cookie_datetime::get_formatted() NOEXCEPT { 37 | return this->date.get_formatted()+" "+this->time.get_formatted(); 38 | } -------------------------------------------------------------------------------- /src/cookie_time.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: cookie_time.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "cookie_time.h" 7 | 8 | using std::ostringstream; 9 | 10 | // Implementation of constructor with parameters. 11 | curl::cookie_time::cookie_time(const unsigned int hour, const unsigned int minutes, 12 | const unsigned int seconds) { 13 | 14 | this->set_hour(hour)->set_minutes(minutes)->set_seconds(seconds); 15 | } 16 | 17 | // Implementation of set_hour method. 18 | curl::cookie_time *curl::cookie_time::set_hour(unsigned int _hour) NOEXCEPT { 19 | this->hour = _hour > 23 ? 0 : _hour; 20 | return this; 21 | } 22 | 23 | // Implementation of set_minutes method. 24 | curl::cookie_time *curl::cookie_time::set_minutes(unsigned int _minutes) NOEXCEPT { 25 | this->minutes = _minutes > 59 ? 0 : _minutes; 26 | return this; 27 | } 28 | 29 | // Implementation of set_seconds method. 30 | curl::cookie_time *curl::cookie_time::set_seconds(unsigned int _seconds) NOEXCEPT { 31 | this->seconds = _seconds > 59 ? 0 : _seconds; 32 | return this; 33 | } 34 | 35 | // Implementation of get_hour method. 36 | unsigned int curl::cookie_time::get_hour() const NOEXCEPT { 37 | return this->hour; 38 | } 39 | 40 | // Implementation of get_minutes method. 41 | unsigned int curl::cookie_time::get_minutes() const NOEXCEPT { 42 | return this->minutes; 43 | } 44 | 45 | // Implementation of get_seconds method. 46 | unsigned int curl::cookie_time::get_seconds() const NOEXCEPT { 47 | return this->seconds; 48 | } 49 | 50 | // Implementation of get_formatted method. 51 | std::string curl::cookie_time::get_formatted() const NOEXCEPT { 52 | ostringstream stream; 53 | stream<get_hour()<<":"<get_minutes()<<":"<get_seconds()<<" GMT"; 54 | return stream.str(); 55 | } -------------------------------------------------------------------------------- /src/curl_cookie.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_cookie.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include 7 | 8 | #include "curl_cookie.h" 9 | 10 | using std::vector; 11 | using std::string; 12 | using std::ostringstream; 13 | 14 | namespace curl { 15 | // Implementation of the get method. 16 | curlcpp_cookies curl_cookie::get() const NOEXCEPT { 17 | auto info = this->easy.get_info(); 18 | return info.get(); 19 | } 20 | 21 | // Implementation of set_cookie_file method. 22 | void curl_cookie::set_file(const string& file = "") { 23 | this->easy.add(file.c_str()); 24 | } 25 | 26 | // Implementation of set_cookie_list method. 27 | void curl_cookie::set(curl::cookie &cookie) { 28 | this->easy.add(cookie.get_formatted().c_str()); 29 | } 30 | 31 | // Implementation of overloaded set_cookie_list method. 32 | void curl_cookie::set(const vector &cookies) { 33 | for (auto c : cookies) { 34 | this->set(c); 35 | } 36 | } 37 | 38 | // Implementation of erase method. 39 | void curl_cookie::erase() { 40 | this->easy.add("ALL"); 41 | } 42 | 43 | // Implementation of flush method. 44 | void curl_cookie::flush() { 45 | this->easy.add("FLUSH"); 46 | } 47 | 48 | // Implementation of erase_session method. 49 | void curl_cookie::erase_session() { 50 | this->easy.add("SESS"); 51 | } 52 | 53 | // Implementation of reload method. 54 | void curl_cookie::reload() { 55 | this->easy.add("RELOAD"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/curl_easy.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_easy.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "curl_easy.h" 7 | 8 | using curl::curl_easy; 9 | using std::ostream; 10 | using std::string; 11 | 12 | // Implementation of default constructor. 13 | curl_easy::curl_easy() : curl_interface() { 14 | this->curl = curl_easy_init(); 15 | if (this->curl == nullptr) { 16 | throw curl_easy_exception("Null pointer intercepted",__FUNCTION__); 17 | } 18 | curl_ios writer; 19 | this->add(writer.get_function()); 20 | this->add(static_cast(writer.get_stream())); 21 | this->add(writer.get_function()); 22 | this->add(static_cast(writer.get_stream())); 23 | } 24 | 25 | // Implementation of overridden constructor. 26 | curl_easy::curl_easy(const long flag) : curl_interface(flag) { 27 | this->curl = curl_easy_init(); 28 | if (this->curl == nullptr) { 29 | throw curl_easy_exception("Null pointer intercepted",__FUNCTION__); 30 | } 31 | curl_ios writer; 32 | this->add(writer.get_function()); 33 | this->add(static_cast(writer.get_stream())); 34 | } 35 | 36 | // Implementation of copy constructor to respect the rule of three. 37 | curl_easy::curl_easy(const curl_easy &easy) : curl_interface(), curl(nullptr) { 38 | *this = easy; 39 | // Let's use a duplication handle function provided by libcurl. 40 | this->curl = curl_easy_duphandle(easy.curl); 41 | } 42 | 43 | // Implementation of move constructor 44 | curl_easy::curl_easy(curl_easy &&other) NOEXCEPT : curl_interface(), curl(nullptr) { 45 | this->curl = other.curl; 46 | // Other's pointer is set to nullptr so that destructor doesn't call the 47 | // cleanup function. 48 | other.curl = nullptr; 49 | } 50 | 51 | // Implementation of assignment operator to perform a deep copy. 52 | curl_easy &curl_easy::operator=(const curl_easy &easy) { 53 | if (this == &easy) { 54 | return *this; 55 | } 56 | curl_easy_cleanup(this->curl); 57 | // We use the duplication handle function also here. 58 | this->curl = curl_easy_duphandle(easy.curl); 59 | return *this; 60 | } 61 | 62 | // Implementation of equality operator overload. 63 | bool curl_easy::operator==(const curl_easy &easy) const { 64 | return this->curl == easy.curl; 65 | } 66 | 67 | // Implementation of destructor. 68 | curl_easy::~curl_easy() NOEXCEPT { 69 | if (this->curl != nullptr) { 70 | curl_easy_cleanup(this->curl); 71 | this->curl = nullptr; 72 | } 73 | } 74 | 75 | // Implementation of abstract method perform. 76 | void curl_easy::perform() { 77 | const CURLcode code = curl_easy_perform(this->curl); 78 | if (code != CURLE_OK) { 79 | throw curl_easy_exception(code,__FUNCTION__); 80 | } 81 | } 82 | 83 | // Implementation of escape method. 84 | void curl_easy::escape(string &url) { 85 | std::unique_ptr url_encoded(curl_easy_escape(this->curl, url.c_str(), (int)url.length()), 86 | [](char *ptr) { curl_free(ptr); }); 87 | 88 | if (!url_encoded) { 89 | throw curl_easy_exception("Null pointer intercepted", __FUNCTION__); 90 | } 91 | url = string(url_encoded.get()); 92 | } 93 | 94 | // Implementation of unescape method. 95 | void curl_easy::unescape(string &url) { 96 | std::unique_ptr url_decoded(curl_easy_unescape(this->curl,url.c_str(),(int)url.length(), 97 | nullptr),[](char *ptr) { curl_free(ptr); }); 98 | 99 | if (url_decoded == nullptr) { 100 | throw curl_easy_exception("Null pointer intercepted",__FUNCTION__); 101 | } 102 | url = string(url_decoded.get()); 103 | } 104 | 105 | // Implementation of reset method. 106 | void curl_easy::reset() NOEXCEPT { 107 | curl_easy_reset(this->curl); 108 | } 109 | 110 | // Implementation of pause method. 111 | void curl_easy::pause(const int bitmask) { 112 | const CURLcode code = curl_easy_pause(this->curl,bitmask); 113 | if (code != CURLE_OK) { 114 | throw curl_easy_exception(code,__FUNCTION__); 115 | } 116 | } -------------------------------------------------------------------------------- /src/curl_exception.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_exception.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "curl_exception.h" 7 | 8 | using curl::curl_exception; 9 | using curl::curlcpp_traceback; 10 | 11 | // Need to define the traceback here to separate declaration from definition, or we'll get a linker error... 12 | curlcpp_traceback curl::curl_exception::traceback; 13 | // ... same for the traceback mutex. 14 | std::mutex curl::curl_exception::tracebackLocker; 15 | 16 | // Constructor implementation. Every call will push into the calls stack the function name and the error occurred. 17 | curl_exception::curl_exception(const std::string &error, const std::string &fun_name) NOEXCEPT 18 | : std::runtime_error(error) { 19 | 20 | curl_exception::tracebackLocker.lock(); 21 | 22 | curl_exception::traceback.insert( 23 | curl_exception::traceback.begin(),curlcpp_traceback_object(error,fun_name)); 24 | 25 | curl_exception::tracebackLocker.unlock(); 26 | } 27 | 28 | // Copy constructor implementation. It makes a copy of the traceback in a thread safe way. 29 | curl_exception::curl_exception(const curl_exception &object) NOEXCEPT : std::runtime_error(object.what()) { 30 | curl_exception::traceback = object.get_traceback(); 31 | } 32 | 33 | // Assignment operator implementation. Implement the assignment operation in a thread safe way avoiding self assignment. 34 | curl_exception& curl_exception::operator=(curl_exception const &object) { 35 | if (&object != this) { 36 | curl_exception::traceback = object.get_traceback(); 37 | } 38 | return *this; 39 | } 40 | -------------------------------------------------------------------------------- /src/curl_form.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_form.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include 7 | #include "curl_form.h" 8 | 9 | using curl::curl_form; 10 | using curl::curl_pair; 11 | 12 | using std::string; 13 | using std::vector; 14 | using std::bad_alloc; 15 | 16 | // Implementation of constructor. 17 | curl_form::curl_form() : form_post(nullptr), last_ptr(nullptr) { 18 | // ... nothing to do here ... 19 | } 20 | 21 | // Implementation of destructor. 22 | curl_form::~curl_form() NOEXCEPT { 23 | if (this->form_post != nullptr) { 24 | curl_formfree(this->form_post); 25 | this->form_post = nullptr; 26 | this->last_ptr = nullptr; 27 | } 28 | } 29 | 30 | // Implementation of assignment operator. Also here, we must perform a deep copy of the entire list. 31 | curl_form &curl_form::operator=(const curl_form &form) { 32 | if (this == &form) { 33 | return *this; 34 | } 35 | curl_formfree(this->form_post); 36 | struct curl_httppost *old_head = form.form_post; 37 | while (old_head != nullptr) { 38 | if (this->form_post == nullptr) { 39 | this->is_null(this->last_ptr = this->form_post = 40 | (struct curl_httppost *)malloc(sizeof(struct curl_httppost))); 41 | 42 | this->copy_ptr(&this->last_ptr,old_head); 43 | } else { 44 | this->is_null(this->last_ptr->next = (struct curl_httppost *)malloc(sizeof(struct curl_httppost))); 45 | this->copy_ptr(&this->last_ptr->next,old_head); 46 | this->last_ptr = this->last_ptr->next; 47 | } 48 | old_head = old_head->next; 49 | } 50 | return *this; 51 | } 52 | 53 | // Implementation of add method. 54 | void curl_form::add(const curl_pair &form_name, 55 | const curl_pair &form_content) { 56 | 57 | if (curl_formadd(&this->form_post,&this->last_ptr, 58 | form_name.first(),form_name.second(), 59 | form_content.first(),form_content.second(), 60 | CURLFORM_END) != 0) { 61 | 62 | throw curl_exception("Error while adding the form",__FUNCTION__); 63 | } 64 | } 65 | 66 | // Implementation of overloaded add method. 67 | void curl_form::add(const curl_pair &form_name, 68 | const curl_pair &form_content, 69 | const curl_pair &content_type) { 70 | 71 | if (curl_formadd(&this->form_post,&this->last_ptr, 72 | form_name.first(),form_name.second(), 73 | form_content.first(),form_content.second(), 74 | content_type.first(),content_type.second(), 75 | CURLFORM_END) != 0) { 76 | 77 | throw curl_exception("Error while adding the form",__FUNCTION__); 78 | } 79 | } 80 | 81 | void curl_form::add(const curl_pair &form_name, 82 | const curl_pair &form_content, 83 | const curl_pair &content_length) { 84 | 85 | if (curl_formadd(&this->form_post,&this->last_ptr, 86 | form_name.first(),form_name.second(), 87 | form_content.first(),form_content.second(), 88 | content_length.first(),content_length.second(), 89 | CURLFORM_END) != 0) { 90 | 91 | throw curl_exception("Error while adding the form",__FUNCTION__); 92 | } 93 | } 94 | 95 | // Implementation of add overloaded method. 96 | void curl_form::add(const curl_pair &form_name, 97 | const curl_pair &name_length, 98 | const curl_pair &form_content) { 99 | 100 | if (curl_formadd(&this->form_post,&this->last_ptr, 101 | form_name.first(),form_name.second(), 102 | form_content.first(),form_content.second(), 103 | name_length.first(),name_length.second(), 104 | CURLFORM_END) != 0) { 105 | 106 | throw curl_exception("Error while adding the form",__FUNCTION__); 107 | } 108 | } 109 | 110 | // Implementation of add overloaded method. 111 | void curl_form::add(const curl_pair &form_name, 112 | const curl_pair &form_content, 113 | const curl_pair &content_length, 114 | const curl_pair &content_type) { 115 | 116 | if (curl_formadd(&this->form_post,&this->last_ptr, 117 | form_name.first(),form_name.second(), 118 | form_content.first(),form_content.second(), 119 | content_length.first(),content_length.second(), 120 | content_type.first(),content_type.second(), 121 | CURLFORM_END) != 0) { 122 | 123 | throw curl_exception("Error while adding the form",__FUNCTION__); 124 | } 125 | } 126 | 127 | // Implementation of add overloaded method for CURLFORM_BUFFERPTR uses 128 | void curl_form::add(const curl_pair &form_name, 129 | const curl_pair &form_bufname, 130 | const curl_pair &form_content, 131 | const curl_pair &content_length) { 132 | 133 | if (curl_formadd(&this->form_post,&this->last_ptr, 134 | form_name.first(),form_name.second(), 135 | form_bufname.first(),form_bufname.second(), 136 | form_content.first(),form_content.second(), 137 | content_length.first(),content_length.second(), 138 | CURLFORM_END) != 0) { 139 | 140 | throw curl_exception("Error while adding the form",__FUNCTION__); 141 | } 142 | } 143 | 144 | /** 145 | * If you want to upload more than one file, you can pass the form name and a 146 | * vector of filenames. 147 | */ 148 | void curl_form::add(const curl_pair &form_name, const vector &files) { 149 | const size_t size = files.size(); 150 | struct curl_forms *new_files; 151 | this->is_null(new_files = new struct curl_forms[size]); 152 | 153 | for (size_t i = 0; i < size; ++i) { 154 | new_files[i].option = CURLFORM_FILE; 155 | new_files[i].value = files[i].c_str(); 156 | } 157 | 158 | if (curl_formadd(&this->form_post,&this->last_ptr, 159 | form_name.first(),form_name.second(), 160 | CURLFORM_ARRAY,new_files, 161 | CURLFORM_END) != 0) { 162 | delete []new_files; 163 | 164 | throw curl_exception("Error while adding the form",__FUNCTION__); 165 | } 166 | delete []new_files; 167 | } 168 | 169 | /** 170 | * Helper function used to copy the curl_httppost list in the copy constructor, to reduce code verbosity. 171 | * We must allocate a pointer for every single pointer data in the old list to perform a complete deep 172 | * copy. 173 | */ 174 | void curl_form::copy_ptr(struct curl_httppost **ptr, const struct curl_httppost *old_ptr) { 175 | if (old_ptr->name) { 176 | this->is_null((*ptr)->name = (char *)malloc(old_ptr->namelength*sizeof(char))); 177 | strcpy((*ptr)->name,old_ptr->name); 178 | // Copy the namelength 179 | (*ptr)->namelength = old_ptr->namelength; 180 | } 181 | if (old_ptr->buffer) { 182 | // Copy the buffers 183 | this->is_null((*ptr)->buffer = (char *)malloc(old_ptr->bufferlength*sizeof(char))); 184 | strcpy((*ptr)->buffer,old_ptr->buffer); 185 | // Copy the buffer length 186 | (*ptr)->bufferlength = old_ptr->bufferlength; 187 | } 188 | if (old_ptr->contents) { 189 | // Copy the contents 190 | this->is_null((*ptr)->contents = (char *)malloc(old_ptr->contentslength*sizeof(char))); 191 | strcpy((*ptr)->contents,old_ptr->contents); 192 | // Copy contents length 193 | (*ptr)->contentslength = old_ptr->contentslength; 194 | } 195 | if (old_ptr->contenttype) { 196 | // Copy content type 197 | this->is_null((*ptr)->contenttype = (char *)malloc(strlen(old_ptr->contenttype)*sizeof(char))); 198 | strcpy((*ptr)->contenttype,old_ptr->contenttype); 199 | } 200 | if (old_ptr->showfilename) { 201 | // Copy file name 202 | this->is_null((*ptr)->showfilename = (char *)malloc(strlen(old_ptr->showfilename)*sizeof(char))); 203 | strcpy((*ptr)->showfilename,old_ptr->showfilename); 204 | } 205 | // Copy flags 206 | (*ptr)->flags = old_ptr->flags; 207 | } 208 | -------------------------------------------------------------------------------- /src/curl_global.cpp: -------------------------------------------------------------------------------- 1 | #include "curl_global.h" 2 | 3 | using curl::curl_global; 4 | 5 | curl_global::curl_global() { 6 | const CURLcode code = curl_global_init(CURL_GLOBAL_ALL); 7 | if (code != CURLE_OK) { 8 | throw curl_easy_exception(code, __FUNCTION__); 9 | } 10 | } 11 | 12 | curl_global::curl_global(const long flag) { 13 | const CURLcode code = curl_global_init(flag); 14 | if (code != CURLE_OK) { 15 | throw curl_easy_exception(code, __FUNCTION__); 16 | } 17 | } 18 | 19 | curl_global::~curl_global() { 20 | curl_global_cleanup(); 21 | } 22 | -------------------------------------------------------------------------------- /src/curl_header.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_header.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "curl_header.h" 7 | #include "curl_exception.h" 8 | #include 9 | 10 | using std::for_each; 11 | using std::initializer_list; 12 | using std::string; 13 | 14 | namespace curl 15 | { 16 | // Implementation of constructor. 17 | curl_header::curl_header() : size(0), headers(nullptr) 18 | { 19 | // ... nothing to do here ... 20 | } 21 | 22 | // Implementation of the list constructor initialize method. 23 | curl_header::curl_header(initializer_list headers) : size(0), headers(nullptr) 24 | { 25 | for_each(headers.begin(), headers.end(), [this](const string &header) 26 | { this->add(header); }); 27 | } 28 | 29 | /** 30 | * Implementation of assignment operator. The object has just been created, so its members have just 31 | * been loaded in memory, so we need to give a valid value to them (in this case just to "headers"). 32 | */ 33 | curl_header &curl_header::operator=(const curl_header &header) 34 | { 35 | if (this == &header) 36 | { 37 | return *this; 38 | } 39 | curl_slist_free_all(this->headers); 40 | struct curl_slist *tmp_ptr = header.headers; 41 | while (tmp_ptr != nullptr) 42 | { 43 | this->add(tmp_ptr->data); 44 | tmp_ptr = tmp_ptr->next; 45 | } 46 | return *this; 47 | } 48 | 49 | // Implementation of destructor. 50 | curl_header::~curl_header() NOEXCEPT 51 | { 52 | if (this->headers != nullptr) 53 | { 54 | curl_slist_free_all(this->headers); 55 | this->headers = nullptr; 56 | } 57 | } 58 | 59 | // Implementation of add overloaded method. 60 | void curl_header::add(const string &header) 61 | { 62 | this->headers = curl_slist_append(this->headers, header.c_str()); 63 | if (this->headers == nullptr) 64 | { 65 | throw curl_exception("Null pointer exception", __FUNCTION__); 66 | } 67 | ++this->size; 68 | } 69 | } -------------------------------------------------------------------------------- /src/curl_info.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_info.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "curl_info.h" 7 | 8 | using curl::curl_info; 9 | using std::string; 10 | using std::list; 11 | 12 | 13 | // Implementation of default constructor. 14 | curl_info::curl_info() { 15 | this->version = curl_version_info(CURLVERSION_NOW); 16 | } 17 | 18 | // Implementation of overloaded constructor. 19 | curl_info::curl_info(const CURLversion version) { 20 | this->version = curl_version_info(version); 21 | } 22 | 23 | // Implementation of get_protocols method. 24 | list curl_info::get_protocols() const NOEXCEPT { 25 | list protocols; 26 | const char *const *const prot = this->version->protocols; 27 | unsigned int i = 0; 28 | while (*(prot+i) != nullptr) { 29 | protocols.emplace_back(string(*(prot+i))); 30 | i++; 31 | } 32 | return protocols; 33 | } 34 | -------------------------------------------------------------------------------- /src/curl_multi.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_multi.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "curl_multi.h" 7 | 8 | using curl::curl_multi; 9 | using curl::curl_easy; 10 | 11 | using std::vector; 12 | using std::unique_ptr; 13 | 14 | void curl_multi::multi_deleter::operator()(CURLM* ptr) const { 15 | curl_multi_cleanup(ptr); 16 | } 17 | 18 | curl_multi::curl_multi() : curl_multi(CURL_GLOBAL_ALL) {} 19 | 20 | curl_multi::curl_multi(const long flag) : curl_interface(flag), curl(curl_multi_init()) { 21 | if (this->curl == nullptr) { 22 | throw curl_multi_exception("Null pointer intercepted", __FUNCTION__); 23 | } 24 | this->active_transfers = 0; 25 | this->message_queued = 0; 26 | } 27 | 28 | curl_multi::curl_multi(curl_multi&& other) NOEXCEPT : curl_interface(std::forward(other)), 29 | curl(std::move(other.curl)), 30 | active_transfers(other.active_transfers), 31 | message_queued(other.message_queued) { 32 | } 33 | 34 | curl_multi &curl_multi::operator=(curl_multi&& other) NOEXCEPT { 35 | if (this != &other) { 36 | curl = std::move(other.curl); 37 | active_transfers = other.active_transfers; 38 | message_queued = other.message_queued; 39 | } 40 | return *this; 41 | } 42 | 43 | curl_multi::~curl_multi() NOEXCEPT = default; 44 | 45 | // Implementation of add method for easy handlers. 46 | void curl_multi::add(const curl_easy &easy) { 47 | const CURLMcode code = curl_multi_add_handle(this->curl.get(),easy.get_curl()); 48 | if (code == CURLM_OK) { 49 | handles[easy.get_curl()] = (curl_easy*)&easy; 50 | } else { 51 | throw curl_multi_exception(code,__FUNCTION__); 52 | } 53 | } 54 | 55 | // Implementation of add method for a vector of easy handlers. 56 | void curl_multi::add(const std::vector &easy_handlers) { 57 | for (const auto& easy_handler : easy_handlers) { 58 | this->add(easy_handler); 59 | } 60 | } 61 | 62 | // Implementation of remove for easy handlers. 63 | void curl_multi::remove(const curl_easy &easy) { 64 | const CURLMcode code = curl_multi_remove_handle(this->curl.get(),easy.get_curl()); 65 | if (code == CURLM_OK) { 66 | handles.erase(easy.get_curl()); 67 | } else { 68 | throw curl_multi_exception(code,__FUNCTION__); 69 | } 70 | } 71 | 72 | // Implementation of get_next_finished method. 73 | std::unique_ptr curl_multi::get_next_finished() { 74 | CURLMsg *message = curl_multi_info_read(this->curl.get(),&this->message_queued); 75 | if (!message || message->msg != CURLMSG_DONE) { 76 | return nullptr; 77 | } 78 | 79 | std::unordered_map::const_iterator it = this->handles.find(message->easy_handle); 80 | if (it != this->handles.end()) { 81 | return unique_ptr(new curl_multi::curl_message(message, it->second)); 82 | } 83 | return nullptr; 84 | } 85 | 86 | // Implementation of perform method. 87 | bool curl_multi::perform() { 88 | const CURLMcode code = curl_multi_perform(this->curl.get(),&this->active_transfers); 89 | if (code == CURLM_CALL_MULTI_PERFORM) { 90 | return false; 91 | } 92 | if (code != CURLM_OK) { 93 | throw curl_multi_exception(code,__FUNCTION__); 94 | } 95 | return true; 96 | } 97 | 98 | // Implementation of socket_action method. 99 | bool curl_multi::socket_action(const curl_socket_t sockfd, const int ev_bitmask) { 100 | const CURLMcode code = curl_multi_socket_action(this->curl.get(),sockfd,ev_bitmask,&this->active_transfers); 101 | if (code == CURLM_CALL_MULTI_PERFORM) { 102 | return false; 103 | } 104 | if (code != CURLM_OK) { 105 | throw curl_multi_exception(code,__FUNCTION__); 106 | } 107 | return true; 108 | } 109 | 110 | // Implementation of set_fd method. 111 | void curl_multi::set_descriptors(fd_set *read, fd_set *write, fd_set *exec, int *max_fd) { 112 | const CURLMcode code = curl_multi_fdset(this->curl.get(),read,write,exec,max_fd); 113 | if (code != CURLM_OK) { 114 | throw curl_multi_exception(code,__FUNCTION__); 115 | } 116 | } 117 | 118 | // Implementation of wait method. 119 | void curl_multi::wait(struct curl_waitfd extra_fds[], const unsigned int extra_nfds, const int timeout_ms, int *numfds) { 120 | const CURLMcode code = curl_multi_wait(this->curl.get(),extra_fds,extra_nfds,timeout_ms,numfds); 121 | if (code != CURLM_OK) { 122 | throw curl_multi_exception(code,__FUNCTION__); 123 | } 124 | } 125 | 126 | // Implementation of assign method. 127 | void curl_multi::assign(const curl_socket_t sockfd, void *sockptr) { 128 | const CURLMcode code = curl_multi_assign(this->curl.get(),sockfd,sockptr); 129 | if (code != CURLM_OK) { 130 | throw curl_multi_exception(code,__FUNCTION__); 131 | } 132 | } 133 | 134 | // Implementation of timeout method. 135 | void curl_multi::timeout(long *timeout) { 136 | const CURLMcode code = curl_multi_timeout(this->curl.get(),timeout); 137 | if (code != CURLM_OK) { 138 | throw curl_multi_exception(code,__FUNCTION__); 139 | } 140 | } 141 | 142 | // Implementation of curl_message constructor. 143 | curl_multi::curl_message::curl_message(const CURLMsg *msg, const curl_easy *handler) : 144 | message(msg->msg), whatever(msg->data.whatever), code(msg->data.result), handler(handler) { 145 | 146 | // ... nothing to do here ... 147 | } 148 | 149 | // Implementation of get_curl method. 150 | CURLM *curl_multi::get_curl() const { 151 | return this->curl.get(); 152 | } 153 | -------------------------------------------------------------------------------- /src/curl_share.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * File: curl_share.cpp 3 | * Author: Giuseppe Persico 4 | */ 5 | 6 | #include "curl_share.h" 7 | 8 | using curl::curl_share; 9 | 10 | // Implementation of default constructor. 11 | curl_share::curl_share() : curl_interface() { 12 | initialize_curl_share(); 13 | } 14 | 15 | // Implementation of assignment operator to perform a deep copy. 16 | curl_share &curl_share::operator=(const curl::curl_share &share) { 17 | if (this != &share) { 18 | return *this; 19 | } 20 | initialize_curl_share(); 21 | return *this; 22 | } 23 | 24 | // Implementation of destructor 25 | curl_share::~curl_share() NOEXCEPT { 26 | if (this->curl != nullptr) { 27 | curl_share_cleanup(this->curl); 28 | this->curl = nullptr; 29 | } 30 | } 31 | 32 | void curl_share::initialize_curl_share() { 33 | this->curl = curl_share_init(); 34 | if (this->curl == nullptr) { 35 | throw curl_share_exception("Null pointer intercepted",__FUNCTION__); 36 | } 37 | } -------------------------------------------------------------------------------- /src/curlcpp.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | includedir=@includedir_for_pc_file@ 4 | libdir=@libdir_for_pc_file@ 5 | 6 | Name: @PROJECT_NAME@ 7 | Description: @CMAKE_PROJECT_DESCRIPTION@ 8 | URL: @CMAKE_PROJECT_HOMEPAGE_URL@ 9 | Version: @PROJECT_VERSION@ 10 | Requires: libcurl >= @CURL_MIN_VERSION@ 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} -lcurlcpp 13 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10...3.15) 2 | 3 | project(test) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | 7 | include_directories("/usr/local/include") 8 | 9 | 10 | add_executable(cookie_example_exec cookie.cpp) 11 | add_executable(custom_request_example_exec custom_request.cpp) 12 | add_executable(easy_example_exec easy.cpp) 13 | add_executable(easy_info_example_exec easy_info.cpp) 14 | add_executable(header_example_exec header.cpp) 15 | add_executable(recv_header_example_exec recv_header.cpp) 16 | add_executable(multi_example_exec multi.cpp) 17 | 18 | target_link_libraries(cookie_example_exec curlcpp) 19 | target_link_libraries(custom_request_example_exec curlcpp) 20 | target_link_libraries(easy_example_exec curlcpp) 21 | target_link_libraries(easy_info_example_exec curlcpp) 22 | target_link_libraries(header_example_exec curlcpp) 23 | target_link_libraries(recv_header_example_exec curlcpp) 24 | target_link_libraries(multi_example_exec curlcpp) 25 | -------------------------------------------------------------------------------- /test/cookie.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "curlcpp/curl_easy.h" 4 | #include "curlcpp/curl_exception.h" 5 | #include "curlcpp/curl_cookie.h" 6 | #include "curlcpp/curl_ios.h" 7 | #include "curlcpp/cookie_datetime.h" 8 | 9 | using std::ostringstream; 10 | 11 | using curl::cookie; 12 | using curl::curl_easy; 13 | using curl::curl_easy_exception; 14 | using curl::curl_cookie; 15 | using curl::curlcpp_cookies; 16 | using curl::curl_ios; 17 | using curl::cookie_date; 18 | using curl::cookie_time; 19 | using curl::cookie_datetime; 20 | 21 | /** 22 | * This example shows to how to set and get cookies in a 23 | * simple curl request. 24 | */ 25 | 26 | int main() { 27 | // Let's declare a stream 28 | ostringstream stream; 29 | // We are going to put the request's output in the previously declared stream 30 | curl_ios ios(stream); 31 | 32 | // Easy object to handle the connection, url and verbosity level. 33 | curl_easy easy(ios); 34 | easy.add("http://example.com"); 35 | 36 | // Let's create a cookie which expires at Mon, 27-03-2016 20:30:30 GMT 37 | cookie ck; 38 | cookie_date date(curl::weekdays::MONDAY,27,curl::months::MARCH,2016); 39 | cookie_time time(20,30,30); 40 | cookie_datetime datetime(time,date); 41 | 42 | ck.set_name("nomecookie"); 43 | ck.set_value("valorecookie"); 44 | ck.set_path("/"); 45 | ck.set_domain(".example.com"); 46 | ck.set_datetime(datetime); 47 | 48 | // Create a cookie object and add the previously created cookie. 49 | curl_cookie cookie_object(easy); 50 | cookie_object.set(ck); 51 | 52 | try { 53 | easy.perform(); 54 | 55 | // Retrieve all the cookies for the example.com (as a vector) 56 | curlcpp_cookies cookies = cookie_object.get(); 57 | // Delete all the memory helded cookies. 58 | cookie_object.erase(); 59 | 60 | // Print them all! 61 | for (const auto& cook : cookies) { 62 | std::cout<(header.get()); 25 | // Your URL. 26 | easy.add("http://example.com"); 27 | // Custom request. 28 | easy.add("PUT"); 29 | // You can choose between 1L and 0L (enable verbose video log or disable) 30 | easy.add(0L); 31 | 32 | try { 33 | // Request execution 34 | easy.perform(); 35 | } catch (curl_easy_exception &error) { 36 | // If you want to print the last error. 37 | std::cerr<("http://www.google.it"); 16 | easy.add(1L); 17 | 18 | try { 19 | easy.perform(); 20 | } catch (curl_easy_exception &error) { 21 | // If you want to print the last error. 22 | std::cerr< ios(stream); 22 | 23 | // Declaration of an easy object 24 | curl_easy easy(ios); 25 | 26 | // Add some option to the curl_easy object. 27 | easy.add("http://www.google.it"); 28 | easy.add(1L); 29 | 30 | try { 31 | easy.perform(); 32 | 33 | // Retrieve information about curl current session. 34 | auto x = easy.get_info(); 35 | 36 | /** 37 | * get_info returns a curl_easy_info object. With the get method we retrieve 38 | * the std::pair object associated with it: the first item is the return code of the 39 | * request. The second is the element requested by the specified libcurl macro. 40 | */ 41 | std::cout<(header.get()); 25 | 26 | easy.add("http://example.com"); 27 | easy.add(1L); 28 | 29 | try { 30 | easy.perform(); 31 | } catch (curl_easy_exception &error) { 32 | // If you want to print the last error. 33 | std::cerr< 2 | #include 3 | 4 | #include "curlcpp/curl_easy.h" 5 | #include "curlcpp/curl_multi.h" 6 | #include "curlcpp/curl_ios.h" 7 | 8 | using curl::curl_easy; 9 | using curl::curl_multi; 10 | using curl::curl_ios; 11 | using curl::curl_easy_exception; 12 | using curl::curlcpp_traceback; 13 | 14 | /** 15 | * This example shows how to make multiple requests 16 | * using curl_multi interface. 17 | */ 18 | int main() { 19 | std::vector urls; 20 | urls.emplace_back("https://google.com"); 21 | urls.emplace_back("https://facebook.com"); 22 | urls.emplace_back("https://linkedin.com"); 23 | 24 | // Create a vector of curl easy handlers. 25 | std::vector handlers; 26 | 27 | // Create a vector of curl streams. 28 | std::vector> streams; 29 | 30 | // Create the curl easy handler and associated the streams with it. 31 | for (const auto & url : urls) { 32 | auto *output_stream = new std::ostringstream; 33 | curl_ios curl_stream(*output_stream); 34 | 35 | curl_easy easy(curl_stream); 36 | easy.add(url.c_str()); 37 | easy.add(1L); 38 | 39 | streams.emplace_back(curl_stream); 40 | handlers.emplace_back(easy); 41 | } 42 | 43 | // Create a map of curl pointers to output streams. 44 | std::unordered_map*> easy_streams; 45 | for (int i = 0; i < handlers.size(); ++i) { 46 | easy_streams[handlers.at(i).get_curl()] = (curl_ios*)&streams.at(i); 47 | } 48 | 49 | // Add all the handlers to the curl multi object. 50 | curl_multi multi; 51 | multi.add(handlers); 52 | 53 | try { 54 | // Start the transfers. 55 | multi.perform(); 56 | 57 | // Until there are active transfers, call the perform() API. 58 | while (multi.get_active_transfers()) { 59 | multi.perform(); 60 | 61 | // Extracts the first finished request. 62 | std::unique_ptr message = multi.get_next_finished(); 63 | if (message != nullptr) { 64 | const curl_easy *handler = message->get_handler(); 65 | 66 | // Get the stream associated with the curl easy handler. 67 | curl_ios stream_handler = *easy_streams[handler->get_curl()]; 68 | 69 | auto content = stream_handler.get_stream()->str(); 70 | auto url = handler->get_info(); 71 | auto response_code = handler->get_info(); 72 | auto content_type = handler->get_info(); 73 | auto http_code = handler->get_info(); 74 | 75 | std::cout << "CODE: " << response_code.get() 76 | << ", TYPE: " << content_type.get() 77 | << ", HTTP_CODE: " << http_code.get() 78 | << ", URL: " << url.get() 79 | << ", CONTENT: " << content.substr(0, 10) + " ... " 80 | << std::endl; 81 | } 82 | } 83 | 84 | // Free the memory allocated for easy streams. 85 | for (auto stream : streams) { 86 | delete stream.get_stream(); 87 | } 88 | 89 | } catch (curl_easy_exception &error) { 90 | // If you want to print the last error. 91 | std::cerr< 2 | #include 3 | 4 | #include "curlcpp/curl_easy.h" 5 | #include "curlcpp/curl_form.h" 6 | #include "curlcpp/curl_ios.h" 7 | #include "curlcpp/curl_exception.h" 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::ostringstream; 12 | 13 | using curl::curl_easy; 14 | using curl::curl_ios; 15 | using curl::curl_easy_exception; 16 | using curl::curlcpp_traceback; 17 | 18 | 19 | /** 20 | * This example shows how to put curl output inside a stream (a variable, for 21 | * example) 22 | */ 23 | int main() { 24 | // Create a stringstream object 25 | ostringstream str; 26 | // Create a curl_ios object, passing the stream object. 27 | curl_ios writer(str); 28 | 29 | // Pass the writer to the easy constructor and watch the content returned in that variable! 30 | curl_easy easy(writer); 31 | easy.add("https://google.com"); 32 | easy.add(1L); 33 | 34 | try { 35 | easy.perform(); 36 | 37 | // Print the content of ostringstream. 38 | cout< body(body_var); 20 | // The "header" stream will put the headers into "header_var" 21 | curl_ios header(header_var); 22 | 23 | // Easy object to handle the connection. 24 | curl_easy easy; 25 | 26 | // We will use the default write function 27 | easy.add(header.get_function()); 28 | 29 | // Specify the stream for headers content. 30 | easy.add(header.get_stream()); 31 | 32 | // Specify the stream for body content. 33 | easy.add(body.get_stream()); 34 | easy.add("http://www.example.com"); 35 | 36 | try { 37 | easy.perform(); 38 | 39 | // Let's print ONLY the headers. 40 | std::cout<