1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2021 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <nel/web/http_client_curl.h>
23 #include <nel/misc/debug.h>
24 #include <nel/web/curl_certificates.h>
27 using namespace NLMISC
;
28 using namespace NLWEB
;
34 #define _Curl (CURL *)_CurlStruct
40 size_t CCurlHttpClient::writeDataFromCurl(void *buffer
, size_t size
, size_t nmemb
, void *pHttpClient
)
42 CCurlHttpClient
* httpClient
= static_cast<CCurlHttpClient
*>(pHttpClient
);
43 httpClient
->pushReceivedData((uint8
*)buffer
, (uint
)(size
*nmemb
));
47 // ***************************************************************************
48 bool CCurlHttpClient::connect(const std::string
&/* server */)
50 curl_version_info_data
*vdata
= curl_version_info(CURLVERSION_NOW
);
51 nldebug("Libcurl v%s", vdata
->version
);
52 if ((vdata
->features
& CURL_VERSION_SSL
) == 0)
53 nlwarning("SSL not supported");
55 curl_global_init(CURL_GLOBAL_ALL
);
56 _CurlStruct
= curl_easy_init();
59 curl_global_cleanup();
66 // ***************************************************************************
67 bool CCurlHttpClient::authenticate(const std::string
&user
, const std::string
&password
)
69 _Auth
= user
+ ":" + password
;
73 static const std::string CAFilename
= "cacert.pem"; // https://curl.haxx.se/docs/caextract.html
75 // ***************************************************************************
76 bool CCurlHttpClient::verifyServer(bool verify
)
79 curl_easy_setopt(_Curl
, CURLOPT_SSL_VERIFYPEER
, verify
? 1 : 0);
80 curl_easy_setopt(_Curl
, CURLOPT_SSL_VERIFYHOST
, verify
? 2 : 0);
82 // specify custom CA certs
83 CCurlCertificates::addCertificateFile(CAFilename
);
85 // if supported, use custom SSL context function to load certificates
86 CCurlCertificates::useCertificates(_Curl
);
91 // ***************************************************************************
92 bool CCurlHttpClient::sendRequest(const std::string
& methodWB
, const std::string
&url
, const std::string
&cookieName
, const std::string
&cookieValue
, const std::string
& postParams
, bool verbose
)
95 curl_easy_setopt(_Curl
, CURLOPT_VERBOSE
, 1);
98 curl_easy_setopt(_Curl
, CURLOPT_URL
, url
.c_str());
99 if (url
.length() > 8 && (url
[4] == 's' || url
[4] == 'S')) // 01234 https
101 curl_easy_setopt(_Curl
, CURLOPT_SSL_VERIFYPEER
, m_Verify
? 1L : 0);
102 curl_easy_setopt(_Curl
, CURLOPT_SSL_VERIFYHOST
, m_Verify
? 2L : 0);
108 curl_easy_setopt(_Curl
, CURLOPT_HTTPAUTH
, CURLAUTH_BASIC
); // TODO: CURLAUTH_ANY
109 curl_easy_setopt(_Curl
, CURLOPT_USERPWD
, _Auth
.c_str());
113 if ((methodWB
== "POST") && (!postParams
.empty()))
115 curl_easy_setopt(_Curl
, CURLOPT_POSTFIELDS
, postParams
.c_str());
118 if (!cookieName
.empty())
119 curl_easy_setopt(_Curl
, CURLOPT_COOKIE
, string(cookieName
+"="+cookieValue
).c_str());
121 // Include the header in the response
122 curl_easy_setopt(_Curl
, CURLOPT_HEADER
, 1);
124 // Register the receive callback
125 curl_easy_setopt(_Curl
, CURLOPT_WRITEFUNCTION
, CCurlHttpClient::writeDataFromCurl
);
126 curl_easy_setopt(_Curl
, CURLOPT_WRITEDATA
, this);
128 if (!m_ErrorBuf
.size())
129 m_ErrorBuf
.resize(CURL_ERROR_SIZE
+ 1);
130 m_ErrorBuf
[0] = '\0';
131 curl_easy_setopt(_Curl
, CURLOPT_ERRORBUFFER
, &m_ErrorBuf
[0]);
134 CURLcode res
= curl_easy_perform(_Curl
);
138 nlwarning(&m_ErrorBuf
[0]);
144 curl_easy_getinfo(_Curl
, CURLINFO_RESPONSE_CODE
, &r
);
147 nldebug("%u", (uint
)r
);
153 void CCurlHttpClient::pushReceivedData(uint8
*buffer
, uint size
)
155 _ReceiveBuffer
.insert(_ReceiveBuffer
.end(), buffer
, buffer
+size
);
158 // ***************************************************************************
159 bool CCurlHttpClient::sendGet(const string
&url
, const string
& params
, bool verbose
)
161 return sendRequest("GET", url
+ (params
.empty() ? "" : ("?" + params
)), string(), string(), string(), verbose
);
164 // ***************************************************************************
165 bool CCurlHttpClient::sendGetWithCookie(const string
&url
, const string
&name
, const string
&value
, const string
& params
, bool verbose
)
167 return sendRequest("GET", url
+ (params
.empty() ? "" : ("?" + params
)), name
, value
, string(), verbose
);
170 // ***************************************************************************
171 bool CCurlHttpClient::sendPost(const string
&url
, const string
& params
, bool verbose
)
173 return sendRequest("POST", url
, string(), string(), params
, verbose
);
176 // ***************************************************************************
177 bool CCurlHttpClient::sendPostWithCookie(const string
&url
, const string
&name
, const string
&value
, const string
& params
, bool verbose
)
179 return sendRequest("POST", url
, name
, value
, params
, verbose
);
182 // ***************************************************************************
183 bool CCurlHttpClient::receive(string
&res
, bool verbose
)
187 nldebug("Receiving %u bytes", (uint
)_ReceiveBuffer
.size());
191 if (!_ReceiveBuffer
.empty())
192 res
.assign((const char*)&(*(_ReceiveBuffer
.begin())), _ReceiveBuffer
.size());
193 _ReceiveBuffer
.clear();
197 // ***************************************************************************
198 void CCurlHttpClient::disconnect()
202 curl_easy_cleanup(_Curl
);
204 curl_global_cleanup();
208 CCurlHttpClient CurlHttpClient
;