1+ #ifdef _WIN32
2+ #define NOMINMAX
3+ #define WIN32_LEAN_AND_MEAN
4+ #endif
5+
16#include " CurlClient.h"
27
38#ifdef HTTPS_BACKEND_CURL
49
510#include < algorithm>
6- #include < dlfcn.h>
711#include < stdexcept>
812#include < sstream>
913#include < vector>
1014
15+ // Dynamic library loader
16+ #ifdef _WIN32
17+ #include < windows.h>
18+ #else
19+ #include < dlfcn.h>
20+ #endif
21+
1122typedef struct StringReader
1223{
1324 const std::string *str;
1425 size_t pos;
1526} StringReader;
1627
17- template <typename T> bool loadSymbol (void *handle, const char *name, T &out)
28+ template <class T >
29+ static inline bool loadSymbol (T &var, void *handle, const char *name)
1830{
19- out = (T) dlsym (handle, name);
20- return out != nullptr ;
31+ #ifdef _WIN32
32+ var = (T) GetProcAddress ((HMODULE) handle, name);
33+ #else
34+ var = (T) dlsym (handle, name);
35+ #endif
36+ return var != nullptr ;
2137}
2238
2339CurlClient::Curl::Curl ()
24- : loaded(false )
40+ : handle(nullptr )
41+ , loaded(false )
42+ , global_cleanup(nullptr )
43+ , easy_init(nullptr )
44+ , easy_cleanup(nullptr )
45+ , easy_setopt(nullptr )
46+ , easy_perform(nullptr )
47+ , easy_getinfo(nullptr )
48+ , slist_append(nullptr )
49+ , slist_free_all(nullptr )
2550{
26- void *handle = dlopen (" libcurl.so" , RTLD_LAZY);
51+ #ifdef _WIN32
52+ handle = (void *) LoadLibraryA (" libcurl.dll" );
53+ #else
54+ handle = dlopen (" libcurl.so.4" , RTLD_LAZY);
55+ #endif
2756 if (!handle)
2857 return ;
2958
3059 // Load symbols
31- void (*global_init)( long ) = nullptr ;
32- if (!loadSymbol (handle, " curl_global_init" , global_init ))
60+ decltype (&curl_global_init) global_init = nullptr ;
61+ if (!loadSymbol (global_init, handle, " curl_global_init" ))
3362 return ;
34- if (!loadSymbol (handle, " curl_global_cleanup" , global_cleanup ))
63+ if (!loadSymbol (global_cleanup, handle, " curl_global_cleanup" ))
3564 return ;
36- if (!loadSymbol (handle, " curl_easy_init" , easy_init ))
65+ if (!loadSymbol (easy_init, handle, " curl_easy_init" ))
3766 return ;
38- if (!loadSymbol (handle, " curl_easy_cleanup" , easy_cleanup ))
67+ if (!loadSymbol (easy_cleanup, handle, " curl_easy_cleanup" ))
3968 return ;
40- if (!loadSymbol (handle, " curl_easy_setopt" , easy_setopt ))
69+ if (!loadSymbol (easy_setopt, handle, " curl_easy_setopt" ))
4170 return ;
42- if (!loadSymbol (handle, " curl_easy_perform" , easy_perform ))
71+ if (!loadSymbol (easy_perform, handle, " curl_easy_perform" ))
4372 return ;
44- if (!loadSymbol (handle, " curl_easy_getinfo" , easy_getinfo ))
73+ if (!loadSymbol (easy_getinfo, handle, " curl_easy_getinfo" ))
4574 return ;
46- if (!loadSymbol (handle, " curl_slist_append" , slist_append ))
75+ if (!loadSymbol (slist_append, handle, " curl_slist_append" ))
4776 return ;
48- if (!loadSymbol (handle, " curl_slist_free_all" , slist_free_all ))
77+ if (!loadSymbol (slist_free_all, handle, " curl_slist_free_all" ))
4978 return ;
5079
5180 global_init (CURL_GLOBAL_DEFAULT);
@@ -56,6 +85,13 @@ CurlClient::Curl::~Curl()
5685{
5786 if (loaded)
5887 global_cleanup ();
88+
89+ if (handle)
90+ #ifdef _WIN32
91+ FreeLibrary ((HMODULE) handle);
92+ #else
93+ dlclose (handle);
94+ #endif
5995}
6096
6197static char toUppercase (char c)
@@ -69,12 +105,13 @@ static size_t stringReader(char *ptr, size_t size, size_t nmemb, StringReader *r
69105 const char *data = reader->str ->data ();
70106 size_t len = reader->str ->length ();
71107 size_t maxCount = (len - reader->pos ) / size;
72- size_t desiredBytes = std::min (maxCount, nmemb) * size;
108+ size_t desiredCount = std::min (maxCount, nmemb);
109+ size_t desiredBytes = desiredCount * size;
73110
74111 std::copy (data + reader->pos , data + desiredBytes, ptr);
75112 reader->pos += desiredBytes;
76113
77- return desiredBytes ;
114+ return desiredCount ;
78115}
79116
80117static size_t stringstreamWriter (char *ptr, size_t size, size_t nmemb, std::stringstream *ss)
@@ -109,6 +146,9 @@ HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
109146 Reply reply;
110147 reply.responseCode = 0 ;
111148
149+ // Use sensible default header for later
150+ HTTPSClient::header_map newHeaders = req.headers ;
151+
112152 CURL *handle = curl.easy_init ();
113153 if (!handle)
114154 throw std::runtime_error (" Could not create curl request" );
@@ -117,13 +157,13 @@ HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
117157 curl.easy_setopt (handle, CURLOPT_FOLLOWLOCATION, 1L );
118158
119159 std::string method = req.method ;
120- if (method == " " )
121- method = " GET" ;
160+ if (method. empty () )
161+ method = req. postdata . size () > 0 ? " POST " : " GET" ;
122162 else
123163 std::transform (method.begin (), method.end (), method.begin (), toUppercase);
124164 curl.easy_setopt (handle, CURLOPT_CUSTOMREQUEST, method.c_str ());
125165
126- StringReader reader;
166+ StringReader reader {} ;
127167
128168 if (req.postdata .size () > 0 && (method != " GET" && method != " HEAD" ))
129169 {
@@ -133,11 +173,14 @@ HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
133173 curl.easy_setopt (handle, CURLOPT_READFUNCTION, stringReader);
134174 curl.easy_setopt (handle, CURLOPT_READDATA, &reader);
135175 curl.easy_setopt (handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t ) req.postdata .length ());
176+
177+ if (newHeaders.count (" Content-Type" ) == 0 )
178+ newHeaders[" Content-Type" ] = " application/x-www-form-urlencoded" ;
136179 }
137180
138181 // Curl doesn't copy memory, keep the strings around
139182 std::vector<std::string> lines;
140- for (auto &header : req. headers )
183+ for (auto &header : newHeaders )
141184 {
142185 std::stringstream line;
143186 line << header.first << " : " << header.second ;
0 commit comments