diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 4d1edad07..66d2e1d8e 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -17,8 +17,6 @@ #ifndef CL_GROUP_HTML_H #define CL_GROUP_HTML_H -#include - #include "nel/misc/types_nl.h" #include "nel/gui/interface_group.h" #include "nel/gui/group_scrolltext.h" @@ -27,6 +25,9 @@ #include "nel/gui/group_table.h" #include "nel/gui/libwww_types.h" +// forward declaration +typedef void CURLM; + typedef std::map TStyle; namespace NLGUI @@ -863,11 +864,6 @@ namespace NLGUI // HtmlType download finished void htmlDownloadFinished(const std::string &content, const std::string &type, long code); - - // cURL transfer callbacks - static size_t curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData); - static size_t curlDataCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData); - static size_t curlProgressCallback(void *pCCurlWWWData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); }; // adapter group that store y offset for inputs inside an html form diff --git a/code/nel/include/nel/gui/libwww.h b/code/nel/include/nel/gui/libwww.h index 892e07eb2..64258608e 100644 --- a/code/nel/include/nel/gui/libwww.h +++ b/code/nel/include/nel/gui/libwww.h @@ -20,11 +20,12 @@ #ifndef CL_LIB_WWW_H #define CL_LIB_WWW_H -#include - #include "nel/misc/rgba.h" #include "nel/gui/libwww_types.h" +// forward declaration to avoid curl.h inclusion everywhere +typedef void CURL; + namespace NLGUI { class CCtrlBaseButton; diff --git a/code/nel/src/gui/curl_certificates.cpp b/code/nel/src/gui/curl_certificates.cpp index 34a989287..71e4084b3 100644 --- a/code/nel/src/gui/curl_certificates.cpp +++ b/code/nel/src/gui/curl_certificates.cpp @@ -25,6 +25,14 @@ #include +// for compatibility with older versions +#ifndef CURL_AT_LEAST_VERSION +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) +#endif + + using namespace std; using namespace NLMISC; @@ -81,6 +89,9 @@ namespace NLGUI // get information on CURL curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); + bool useOpenSSLBackend = false; + +#if CURL_AT_LEAST_VERSION(7, 34, 0) // get more information on CURL session curl_tlssessioninfo *sessionInfo; @@ -94,8 +105,30 @@ namespace NLGUI CURLcode res = curl_easy_getinfo(curl, info, &sessionInfo); + // CURL using OpenSSL backend + if ((res == CURLE_OK) && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL) useOpenSSLBackend = true; +#elif CURL_AT_LEAST_VERSION(7, 12, 3) + // get a list of OpenSSL engines + struct curl_slist *engines; + + CURLcode res = curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines); + + // CURL using OpenSSL backend + // With OpenSSL compiled without any engine, engines will too return NULL + // Fortunately, if OpenSSL isn't compiled with engines means we compiled it ourself and CURL is a recent version + if ((res == CURLE_OK) && engine) + { + // free engines + curl_slist_free_all(engines); + + useOpenSSLBackend = true; + } +#else + // TODO: implement an equivalent, but CURL 7.12 was released in 2004 +#endif + // only use OpenSSL callback if not using Windows SSPI and using OpenSSL backend - if (!res && sessionInfo && sessionInfo->backend == CURLSSLBACKEND_OPENSSL && !(data && data->features & CURL_VERSION_SSPI)) + if (useOpenSSLBackend && !(data && data->features & CURL_VERSION_SSPI)) { #ifdef NL_OS_WINDOWS // load native Windows CA Certs @@ -181,7 +214,21 @@ namespace NLGUI void addCertificatesFromFile(const std::string &cert) { - if (!isInitialized || !isUsingOpenSSLBackend) return; + if (!isInitialized) + { + nlwarning("CURL not initialized! Check if there are another errors"); + return; + } + + if (!isUsingOpenSSLBackend) + { + nlinfo("CURL not using OpenSSL backend! Unable to use custom certificates"); + return; + } + else + { + nlinfo("CURL using OpenSSL backend!"); + } // this file was already loaded if (std::find(CertList.begin(), CertList.end(), cert) != CertList.end()) return; diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index b8886881e..b0ecd6ec4 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -49,6 +49,8 @@ #include "nel/gui/http_hsts.h" #include "nel/gui/curl_certificates.h" +#include + using namespace std; using namespace NLMISC; @@ -205,6 +207,47 @@ namespace NLGUI std::map HeadersRecv; }; + // cURL transfer callbacks + // *************************************************************************** + static size_t curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) + { + CCurlWWWData * me = static_cast(pCCurlWWWData); + if (me) + { + std::string header; + header.append(buffer, size * nmemb); + me->setRecvHeader(header.substr(0, header.find_first_of("\n\r"))); + } + + return size * nmemb; + } + + // *************************************************************************** + static size_t curlDataCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) + { + CCurlWWWData * me = static_cast(pCCurlWWWData); + if (me) + me->Content.append(buffer, size * nmemb); + + return size * nmemb; + } + + // *************************************************************************** + static size_t curlProgressCallback(void *pCCurlWWWData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) + { + CCurlWWWData * me = static_cast(pCCurlWWWData); + if (me) + { + if (dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0) + { + nlwarning("> dltotal %d, dlnow %d, ultotal %d, ulnow %d, url '%s'", dltotal, dlnow, ultotal, ulnow, me->Url.c_str()); + } + } + + // return 1 to cancel download + return 0; + } + // Check if domain is on TrustedDomain bool CGroupHTML::isTrustedDomain(const string &domain) { @@ -423,7 +466,7 @@ namespace NLGUI download.data->sendHeaders(headers); // catch headers - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaderCallback); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, NLGUI::curlHeaderCallback); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, download.data); std::string userAgent = options.appName + "/" + options.appVersion; @@ -5478,17 +5521,17 @@ namespace NLGUI _CurlWWW->sendHeaders(headers); // catch headers for redirect - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaderCallback); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, NLGUI::curlHeaderCallback); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, _CurlWWW); // catch body - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlDataCallback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NLGUI::curlDataCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, _CurlWWW); #if LOG_DL // progress callback curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, curlProgressCallback); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, NLGUI::curlProgressCallback); curl_easy_setopt(curl, CURLOPT_XFERINFODATA, _CurlWWW); #else // progress off @@ -6497,46 +6540,6 @@ namespace NLGUI } } - // *************************************************************************** - size_t CGroupHTML::curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) - { - CCurlWWWData * me = static_cast(pCCurlWWWData); - if (me) - { - std::string header; - header.append(buffer, size * nmemb); - me->setRecvHeader(header.substr(0, header.find_first_of("\n\r"))); - } - - return size * nmemb; - } - - // *************************************************************************** - size_t CGroupHTML::curlDataCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) - { - CCurlWWWData * me = static_cast(pCCurlWWWData); - if (me) - me->Content.append(buffer, size * nmemb); - - return size * nmemb; - } - - // *************************************************************************** - size_t CGroupHTML::curlProgressCallback(void *pCCurlWWWData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) - { - CCurlWWWData * me = static_cast(pCCurlWWWData); - if (me) - { - if (dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0) - { - nlwarning("> dltotal %d, dlnow %d, ultotal %d, ulnow %d, url '%s'", dltotal, dlnow, ultotal, ulnow, me->Url.c_str()); - } - } - - // return 1 to cancel download - return 0; - } - // *************************************************************************** std::string CGroupHTML::HTMLOListElement::getListMarkerText() const { diff --git a/code/nel/src/gui/libwww.cpp b/code/nel/src/gui/libwww.cpp index fef3d788e..2e9b4451a 100644 --- a/code/nel/src/gui/libwww.cpp +++ b/code/nel/src/gui/libwww.cpp @@ -19,6 +19,8 @@ #include "nel/gui/libwww.h" #include "nel/gui/group_html.h" +#include + using namespace NLMISC; #ifdef DEBUG_NEW diff --git a/code/ryzom/client/src/interface_v3/group_html_webig.cpp b/code/ryzom/client/src/interface_v3/group_html_webig.cpp index 58d27c851..fe2fa5229 100644 --- a/code/ryzom/client/src/interface_v3/group_html_webig.cpp +++ b/code/ryzom/client/src/interface_v3/group_html_webig.cpp @@ -28,6 +28,8 @@ #include "../net_manager.h" #include "../connection.h" +#include + using namespace std; using namespace NLMISC;