From aeaf04308b06f747751e6fe6e41c538c09378908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Tue, 21 Jul 2020 07:44:23 +0200 Subject: [PATCH 01/10] curl: Initial implementation using libcurl for HTTP download Advantage of libcurl over wxHTTP is that we get HTTPS support out of the box. Disadvantage is it being another dependency. Therefore using libcurl is optional now, but strongly encouraged. Since HTTP download was the last piece of network functions not replaced by Boost.Asio, using libcurl together with boost makes it possible to forget wxWidgets networking completely. --- configure.ac | 7 + m4/libcurl.m4 | 272 +++++++++++++++++++++++++++++++++++++++ src/HTTPDownload.cpp | 67 +++++++++- src/Makefile.am | 4 +- src/amule-remote-gui.cpp | 28 +++- src/amule.cpp | 28 +++- 6 files changed, 396 insertions(+), 10 deletions(-) create mode 100644 m4/libcurl.m4 diff --git a/configure.ac b/configure.ac index c3a40a847d..6d3708488c 100644 --- a/configure.ac +++ b/configure.ac @@ -232,6 +232,11 @@ MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui, fileview], ])]) +# Check for libcurl +MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui], +[LIBCURL_CHECK_CONFIG(,,, [MULE_WARNING([libcurl not found or disabled. Reverting to using wxHTTP for http download, but beware, https won't be supported.])])]) + + MULE_COMPILATION_FLAGS @@ -550,6 +555,8 @@ AS_IF([test ${with_boost:-no} != no], )]) MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui, fileview], [echo " crypto++ ${CRYPTOPP_VERSION_STRING} (in ${CRYPTOPP_PREFIX})"]) +MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui], + [echo " libcurl ${libcurl_cv_lib_curl_version:-Not detected}"]) MULE_IF_ENABLED([upnp], [ AS_IF([test -n "$with_libupnp_prefix"], [libupnp_place=" (in $with_libupnp_prefix)"]) echo " libupnp ${LIBUPNP_VERSION:-Not detected}${libupnp_place:-}" diff --git a/m4/libcurl.m4 b/m4/libcurl.m4 new file mode 100644 index 0000000000..c3c17661ba --- /dev/null +++ b/m4/libcurl.m4 @@ -0,0 +1,272 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2006 - 2020, David Shaw +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], +# [ACTION-IF-YES], [ACTION-IF-NO]) +# ---------------------------------------------------------- +# David Shaw May-09-2006 +# +# Checks for libcurl. DEFAULT-ACTION is the string yes or no to +# specify whether to default to --with-libcurl or --without-libcurl. +# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the +# minimum version of libcurl to accept. Pass the version as a regular +# version number like 7.10.1. If not supplied, any version is +# accepted. ACTION-IF-YES is a list of shell commands to run if +# libcurl was successfully found and passed the various tests. +# ACTION-IF-NO is a list of shell commands that are run otherwise. +# Note that using --without-libcurl does run ACTION-IF-NO. +# +# This macro #defines HAVE_LIBCURL if a working libcurl setup is +# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary +# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are +# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy +# where yyy are the various protocols supported by libcurl. Both xxx +# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of +# the macro for the complete list of possible defines. Shell +# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also +# defined to 'yes' for those features and protocols that were found. +# Note that xxx and yyy keep the same capitalization as in the +# curl-config list (e.g. it's "HTTP" and not "http"). +# +# Users may override the detected values by doing something like: +# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure +# +# For the sake of sanity, this macro assumes that any libcurl that is +# found is after version 7.7.2, the first version that included the +# curl-config script. Note that it is very important for people +# packaging binary versions of libcurl to include this script! +# Without curl-config, we can only guess what protocols are available, +# or use curl_version_info to figure it out at runtime. + +AC_DEFUN([LIBCURL_CHECK_CONFIG], +[ + AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) + AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) + AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) + AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) + AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) + AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN]) + AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI]) + AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM]) + + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) + AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3]) + AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP]) + + AC_ARG_WITH(libcurl, + AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), + [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) + + if test "$_libcurl_with" != "no" ; then + + AC_PROG_AWK + + _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" + + _libcurl_try_link=yes + + if test -d "$_libcurl_with" ; then + LIBCURL_CPPFLAGS="-I$withval/include" + _libcurl_ldflags="-L$withval/lib" + AC_PATH_PROG([_libcurl_config],[curl-config],[], + ["$withval/bin"]) + else + AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH]) + fi + + if test x$_libcurl_config != "x" ; then + AC_CACHE_CHECK([for the version of libcurl], + [libcurl_cv_lib_curl_version], + [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) + + _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` + _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` + + if test $_libcurl_wanted -gt 0 ; then + AC_CACHE_CHECK([for libcurl >= version $2], + [libcurl_cv_lib_version_ok], + [ + if test $_libcurl_version -ge $_libcurl_wanted ; then + libcurl_cv_lib_version_ok=yes + else + libcurl_cv_lib_version_ok=no + fi + ]) + fi + + if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then + if test x"$LIBCURL_CPPFLAGS" = "x" ; then + LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` + fi + if test x"$LIBCURL" = "x" ; then + LIBCURL=`$_libcurl_config --libs` + + # This is so silly, but Apple actually has a bug in their + # curl-config script. Fixed in Tiger, but there are still + # lots of Panther installs around. + case "${host}" in + powerpc-apple-darwin7*) + LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` + ;; + esac + fi + + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` + + # Is it modern enough to have --protocols? (7.12.4) + if test $_libcurl_version -ge 461828 ; then + _libcurl_protocols=`$_libcurl_config --protocols` + fi + else + _libcurl_try_link=no + fi + + unset _libcurl_wanted + fi + + if test $_libcurl_try_link = yes ; then + + # we didn't find curl-config, so let's see if the user-supplied + # link line (or failing that, "-lcurl") is enough. + LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} + + AC_CACHE_CHECK([whether libcurl is usable], + [libcurl_cv_lib_curl_usable], + [ + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBCURL $LIBS" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],[[ +/* Try and use a few common options to force a failure if we are + missing symbols or can't link. */ +int x; +curl_easy_setopt(NULL,CURLOPT_URL,NULL); +x=CURL_ERROR_SIZE; +x=CURLOPT_WRITEFUNCTION; +x=CURLOPT_WRITEDATA; +x=CURLOPT_ERRORBUFFER; +x=CURLOPT_STDERR; +x=CURLOPT_VERBOSE; +if (x) {;} +]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + ]) + + if test $libcurl_cv_lib_curl_usable = yes ; then + + # Does curl_free() exist in this version of libcurl? + # If not, fake it with free() + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBS $LIBCURL" + + AC_CHECK_FUNC(curl_free,, + AC_DEFINE(curl_free,free, + [Define curl_free() as free() if our version of curl lacks curl_free.])) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + + AC_DEFINE(HAVE_LIBCURL,1, + [Define to 1 if you have a functional curl library.]) + AC_SUBST(LIBCURL_CPPFLAGS) + AC_SUBST(LIBCURL) + + for _libcurl_feature in $_libcurl_features ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) + eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes + done + + if test "x$_libcurl_protocols" = "x" ; then + + # We don't have --protocols, so just assume that all + # protocols are available + _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" + + if test x$libcurl_feature_SSL = xyes ; then + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 (0x070b00 == 461568) + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi + fi + + # RTSP, IMAP, POP3 and SMTP were added in + # 7.20.0 (0x071400 == 463872) + if test $_libcurl_version -ge 463872; then + _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" + fi + fi + + for _libcurl_protocol in $_libcurl_protocols ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) + eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes + done + else + unset LIBCURL + unset LIBCURL_CPPFLAGS + fi + fi + + unset _libcurl_try_link + unset _libcurl_version_parse + unset _libcurl_config + unset _libcurl_feature + unset _libcurl_features + unset _libcurl_protocol + unset _libcurl_protocols + unset _libcurl_version + unset _libcurl_ldflags + fi + + if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then + # This is the IF-NO path + ifelse([$4],,:,[$4]) + else + # This is the IF-YES path + ifelse([$3],,:,[$3]) + fi + + unset _libcurl_with +])dnl diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index 11df0565c7..0b46b31d89 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -24,10 +24,17 @@ // -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" // Needed for HAVE_LIBCURL +#endif +#ifdef HAVE_LIBCURL +# include +#else +# include +#endif +#include // Needed for wxFFileOutputStream #include "HTTPDownload.h" // Interface declarations #include // Needed for unicode2char #include "OtherFunctions.h" // Needed for CastChild @@ -185,13 +192,33 @@ wxString CHTTPDownloadThread::FormatDateHTTP(const wxDateTime& date) } +#ifdef HAVE_LIBCURL + +size_t mule_curl_write_callback(char *ptr, size_t WXUNUSED(size), size_t nmemb, void *userdata) +{ + wxFFileOutputStream *outstream = static_cast(userdata); + + // According to the documentation size will always be 1. + outstream->Write(ptr, nmemb); + + return outstream->LastWrite(); +} + +#endif /* HAVE_LIBCURL */ + + CMuleThread::ExitCode CHTTPDownloadThread::Entry() { if (TestDestroy()) { return NULL; } +#ifdef HAVE_LIBCURL + CURL *curl; + CURLcode res; +#else wxHTTP* url_handler = NULL; +#endif AddDebugLogLineN(logHTTP, wxT("HTTP download thread started")); @@ -210,6 +237,35 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() throw wxString(_("The URL to download can't be empty")); } +#ifdef HAVE_LIBCURL + + curl = curl_easy_init(); + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, (const char *)unicode2char(m_url)); + + // follow redirects + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + + // set write callback + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, mule_curl_write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outfile); + + // perform the action + res = curl_easy_perform(curl); + + curl_easy_cleanup(curl); + + // check the result + if (res != CURLE_OK) { + m_result = HTTP_Error; + throw wxString(CFormat(_("HTTP download failed: %s")) % wxString(curl_easy_strerror(res))); + } else { + m_result = HTTP_Success; + } + } + +#else /* == not HAVE_LIBCURL */ + url_handler = new wxHTTP; url_handler->SetProxyMode(use_proxy); @@ -284,6 +340,9 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() m_result = HTTP_Success; } } + +#endif /* ifelse HAVE_LIBCURL */ + } catch (const wxString& error) { if (wxFileExists(m_tempfile)) { wxRemoveFile(m_tempfile); @@ -297,9 +356,11 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() thePrefs::SetLastHTTPDownloadURL(m_file_id, m_url); } +#ifndef HAVE_LIBCURL if (url_handler) { url_handler->Destroy(); } +#endif AddDebugLogLineN(logHTTP, wxT("HTTP download thread ended")); @@ -326,6 +387,7 @@ void CHTTPDownloadThread::OnExit() } +#ifndef HAVE_LIBCURL //! This function's purpose is to handle redirections in a proper way. wxInputStream* CHTTPDownloadThread::GetInputStream(wxHTTP * & url_handler, const wxString& location, bool proxy) { @@ -440,6 +502,7 @@ wxInputStream* CHTTPDownloadThread::GetInputStream(wxHTTP * & url_handler, const return url_read_stream; } +#endif /* !HAVE_LIBCURL */ void CHTTPDownloadThread::StopAll() { diff --git a/src/Makefile.am b/src/Makefile.am index cfde5b4f8f..5e91d59e16 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -231,7 +231,7 @@ common_sources = \ core_libs = -L. -lmuleappcore $(LIBUPNP_LDFLAGS) $(LIBUPNP_LIBS) gui_libs = -L. -lmuleappgui $(WX_LIBS) $(GEOIP_LDFLAGS) $(GEOIP_LIBS) remote_common_libs = -Llibs/common -Llibs/ec/cpp -lmulecommon -lec $(BFD_LIBS) $(ZLIB_LDFLAGS) $(ZLIB_LIBS) $(RESOLV_LIB) -common_libs = -L. -lmuleappcommon $(remote_common_libs) -lmulesocket $(BOOST_SYSTEM_LDFLAGS) $(BOOST_SYSTEM_LIBS) $(CRYPTOPP_LDFLAGS) $(CRYPTOPP_LIBS) +common_libs = -L. -lmuleappcommon $(remote_common_libs) -lmulesocket $(BOOST_SYSTEM_LDFLAGS) $(BOOST_SYSTEM_LIBS) $(CRYPTOPP_LDFLAGS) $(CRYPTOPP_LIBS) $(LIBCURL) core_deps = libmuleappcore.a gui_deps = libmuleappgui.a @@ -247,7 +247,7 @@ endif # core_flags = $(BOOST_CPPFLAGS) $(LIBUPNP_CPPFLAGS) $(LIBUPNP_CFLAGS) gui_flags = $(WX_CPPFLAGS) $(GEOIP_CPPFLAGS) -common_flags = -I$(srcdir)/libs -Ilibs -I$(srcdir)/include $(CRYPTOPP_CPPFLAGS) +common_flags = -I$(srcdir)/libs -Ilibs -I$(srcdir)/include $(CRYPTOPP_CPPFLAGS) $(LIBCURL_CPPFLAGS) # --------- Apps --------- diff --git a/src/amule-remote-gui.cpp b/src/amule-remote-gui.cpp index 724d7438ff..9bec24a239 100644 --- a/src/amule-remote-gui.cpp +++ b/src/amule-remote-gui.cpp @@ -23,12 +23,22 @@ // +#ifdef HAVE_CONFIG_H +# include "config.h" // Needed for HAVE_LIBCURL, ASIO_SOCKETS +#endif + #include #include // Needed for wxCmdLineParser #include // Do_not_auto_remove (win32) #include // Needed for wxFileConfig -#include // Needed for wxSocketBase +#ifdef HAVE_LIBCURL +# include +#endif + +#if !(defined(HAVE_LIBCURL) && defined(ASIO_SOCKETS)) +# include // Needed for wxSocketBase +#endif #include #include @@ -139,7 +149,13 @@ int CamuleRemoteGuiApp::OnExit() { StopTickTimer(); +#ifdef HAVE_LIBCURL + curl_global_cleanup(); +#endif + +#if !(defined(HAVE_LIBCURL) && defined(ASIO_SOCKETS)) wxSocketBase::Shutdown(); // needed because we also called Initialize() manually +#endif return wxApp::OnExit(); } @@ -256,8 +272,16 @@ bool CamuleRemoteGuiApp::OnInit() return false; } - // Initialize wx sockets (needed for http download in background with Asio sockets) +#ifdef HAVE_LIBCURL + if (curl_global_init(CURL_GLOBAL_ALL) != 0) { + return false; + } +#endif + +#if !(defined(HAVE_LIBCURL) && defined(ASIO_SOCKETS)) + // Initialize wx sockets only if we actually use wx networking wxSocketBase::Initialize(); +#endif // Create the polling timer poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT); diff --git a/src/amule.cpp b/src/amule.cpp index fcb984e852..ba07c34984 100644 --- a/src/amule.cpp +++ b/src/amule.cpp @@ -33,8 +33,9 @@ #ifdef HAVE_CONFIG_H #include "config.h" // Needed for HAVE_GETRLIMIT, HAVE_SETRLIMIT, - // HAVE_SYS_RESOURCE_H, HAVE_SYS_STATVFS_H, VERSION - // and ENABLE_NLS + // HAVE_SYS_RESOURCE_H, HAVE_SYS_STATVFS_H, + // HAVE_LIBCURL, ASIO_SOCKETS, + // VERSION and ENABLE_NLS #endif #include @@ -42,10 +43,15 @@ #include // Needed for wxCmdLineParser #include // Do_not_auto_remove (win32) #include -#include #include #include +#ifdef HAVE_LIBCURL +# include +#endif +#if !(defined(HAVE_LIBCURL) && defined(ASIO_SOCKETS)) +# include +#endif #include // Needed for CFormat #include "kademlia/kademlia/Kademlia.h" @@ -327,7 +333,13 @@ int CamuleApp::OnExit() m_AsioService = NULL; #endif +#ifdef HAVE_LIBCURL + curl_global_cleanup(); +#endif + +#if !(defined(HAVE_LIBCURL) && defined(ASIO_SOCKETS)) wxSocketBase::Shutdown(); // needed because we also called Initialize() manually +#endif if (m_app_state!=APP_STATE_STARTING) { AddLogLineNS(_("aMule shutdown completed.")); @@ -415,8 +427,16 @@ bool CamuleApp::OnInit() return false; } - // Initialize wx sockets (needed for http download in background with Asio sockets) +#ifdef HAVE_LIBCURL + if (curl_global_init(CURL_GLOBAL_ALL) != 0) { + return false; + } +#endif + +#if !(defined(HAVE_LIBCURL) && defined(ASIO_SOCKETS)) + // Initialize wx sockets only if we actually use wx networking wxSocketBase::Initialize(); +#endif // Some sanity check if (!thePrefs::UseTrayIcon()) { From 74d5e14c0f38134dc5b2024e16f5254f927cb138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Tue, 22 Sep 2020 01:46:09 +0200 Subject: [PATCH 02/10] curl: Send libcurl verbose messages to aMule debug log --- src/HTTPDownload.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index 0b46b31d89..2d7c6bbca2 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -204,6 +204,16 @@ size_t mule_curl_write_callback(char *ptr, size_t WXUNUSED(size), size_t nmemb, return outstream->LastWrite(); } +#ifdef __DEBUG__ +int mule_curl_debug_callback(CURL* WXUNUSED(handle), curl_infotype type, char *data, size_t WXUNUSED(size), void* WXUNUSED(userptr)) +{ + if (type == CURLINFO_TEXT) { + AddDebugLogLineN(logHTTP, CFormat(wxT("curl: %s")) % wxString(data)); + } + + return 0; +} +#endif #endif /* HAVE_LIBCURL */ @@ -250,6 +260,12 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, mule_curl_write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outfile); +#ifdef __DEBUG__ + // send libcurl verbose messages to aMule debug log + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, mule_curl_debug_callback); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); +#endif + // perform the action res = curl_easy_perform(curl); From 8f38185ef5a6fed89c888b49e3e8a2adf6e8ae53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Wed, 23 Sep 2020 01:32:15 +0200 Subject: [PATCH 03/10] curl: Set a valid "User-Agent" header --- src/HTTPDownload.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index 2d7c6bbca2..215c37ce8b 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -30,6 +30,7 @@ #ifdef HAVE_LIBCURL # include +# include // Needed for the VERSION_ defines #else # include #endif @@ -266,6 +267,10 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif + // some servers don't like requests without a user-agent, so set one + // always use a numerical version value, that's why we don't use VERSION + curl_easy_setopt(curl, CURLOPT_USERAGENT, "aMule/" wxSTRINGIZE(VERSION_MJR) "." wxSTRINGIZE(VERSION_MIN) "." wxSTRINGIZE(VERSION_UPDATE)); + // perform the action res = curl_easy_perform(curl); From 8231e9501c5453a758a55b4af639de2aec8391e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Wed, 23 Sep 2020 01:36:30 +0200 Subject: [PATCH 04/10] curl: Support the "If-Modified-Since" header --- src/HTTPDownload.cpp | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index 215c37ce8b..c778b208e6 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -252,6 +252,8 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl = curl_easy_init(); if (curl) { + struct curl_slist *list = NULL; + curl_easy_setopt(curl, CURLOPT_URL, (const char *)unicode2char(m_url)); // follow redirects @@ -267,6 +269,17 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif + // Build a conditional get request if the last modified date of the file being updated is known + if (m_lastmodified.IsValid()) { + // Set a flag in the HTTP header that we only download if the file is newer. + // see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 + AddDebugLogLineN(logHTTP, wxT("If-Modified-Since: ") + FormatDateHTTP(m_lastmodified)); + list = curl_slist_append(list, (const char *)unicode2char(wxT("If-Modified-Since: ") + FormatDateHTTP(m_lastmodified))); + } + + // set custom header(s) + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + // some servers don't like requests without a user-agent, so set one // always use a numerical version value, that's why we don't use VERSION curl_easy_setopt(curl, CURLOPT_USERAGENT, "aMule/" wxSTRINGIZE(VERSION_MJR) "." wxSTRINGIZE(VERSION_MIN) "." wxSTRINGIZE(VERSION_UPDATE)); @@ -274,15 +287,35 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() // perform the action res = curl_easy_perform(curl); - curl_easy_cleanup(curl); + // clean up + curl_slist_free_all(list); // check the result if (res != CURLE_OK) { m_result = HTTP_Error; + curl_easy_cleanup(curl); throw wxString(CFormat(_("HTTP download failed: %s")) % wxString(curl_easy_strerror(res))); } else { - m_result = HTTP_Success; + long response_code; + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + if (res != CURLE_OK) { + // getinfo() failed, but perform() succeeded. Let's assume the transfer was O.K. + AddDebugLogLineN(logHTTP, wxT("curl_easy_getinfo() failed: ") + wxString(curl_easy_strerror(res))); + m_result = HTTP_Success; + } else { + AddDebugLogLineN(logHTTP, CFormat(wxT("Response code: %d")) % response_code); + if (response_code == 304) { // "Not Modified" + m_result = HTTP_Skipped; + } else if (response_code == 200) { // "OK" + m_result = HTTP_Success; + } else { + m_result = HTTP_Error; + } + } } + + // clean up + curl_easy_cleanup(curl); } #else /* == not HAVE_LIBCURL */ From 9f9ed793bd675670623f059470eb81b7fde70c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Wed, 23 Sep 2020 09:58:24 +0200 Subject: [PATCH 05/10] curl: Show download progress Minimum required libcurl version is now 7.32.0, required by CURLOPT_XFERINFOFUNCTION. Since it's already seven years old, we're not planning to support older versions. --- configure.ac | 2 +- src/HTTPDownload.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6d3708488c..7d15129f8b 100644 --- a/configure.ac +++ b/configure.ac @@ -234,7 +234,7 @@ MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui, fileview], # Check for libcurl MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui], -[LIBCURL_CHECK_CONFIG(,,, [MULE_WARNING([libcurl not found or disabled. Reverting to using wxHTTP for http download, but beware, https won't be supported.])])]) +[LIBCURL_CHECK_CONFIG(, [7.32.0],, [MULE_WARNING([libcurl not found or disabled. Reverting to using wxHTTP for http download, but beware, https won't be supported.])])]) MULE_COMPILATION_FLAGS diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index c778b208e6..a4b02d75d7 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -215,6 +215,21 @@ int mule_curl_debug_callback(CURL* WXUNUSED(handle), curl_infotype type, char *d return 0; } #endif + +#ifndef AMULE_DAEMON +int mule_curl_xferinfo_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t WXUNUSED(ultotal), curl_off_t WXUNUSED(ulnow)) +{ + wxEvtHandler *dialog = static_cast(clientp); + + CMuleInternalEvent evt(wxEVT_HTTP_PROGRESS); + evt.SetInt(dlnow); + evt.SetExtraLong(dltotal); + wxPostEvent(dialog, evt); + + return 0; +} +#endif + #endif /* HAVE_LIBCURL */ @@ -269,6 +284,21 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif +#ifndef AMULE_DAEMON + // show download progress + if (m_companion) { + // CURLOPT_XFERINFOFUNCTION was introduced in 7.32.0. + // We're not planning to support older libcurl versions, thus if + // the runtime library doesn't support CURLOPT_XFERINFOFUNCTION + // (probably because it's too old) we simply won't have a progress meter. + res = curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, mule_curl_xferinfo_callback); + if (res == CURLE_OK) { + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, m_companion); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + } + } +#endif + // Build a conditional get request if the last modified date of the file being updated is known if (m_lastmodified.IsValid()) { // Set a flag in the HTTP header that we only download if the file is newer. From 5ebe232b612709fa7ecc4790c5a556edd4dd332e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Thu, 24 Sep 2020 11:21:33 +0200 Subject: [PATCH 06/10] curl: Bind outgoing connections to the specified interface --- src/HTTPDownload.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index a4b02d75d7..dd4b55a537 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -314,6 +314,11 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() // always use a numerical version value, that's why we don't use VERSION curl_easy_setopt(curl, CURLOPT_USERAGENT, "aMule/" wxSTRINGIZE(VERSION_MJR) "." wxSTRINGIZE(VERSION_MIN) "." wxSTRINGIZE(VERSION_UPDATE)); + // set the outgoing address + if (!thePrefs::GetAddress().empty()) { + curl_easy_setopt(curl, CURLOPT_INTERFACE, (const char *)unicode2char(thePrefs::GetAddress())); + } + // perform the action res = curl_easy_perform(curl); From a87822e14ef2efdc17d431eb1e1575a193e1ec0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Fri, 25 Sep 2020 16:10:00 +0200 Subject: [PATCH 07/10] curl: Print transfer summary after successful download This is mainly a demonstration of how we can select new functionality if available. First, we have to check the compile-time headers version whether they have the new functionality or not, to be able to compile it in. Then, we have to check the library version at runtime because that might very well be different from what we used for compilation. If both checks succeed then and only then can we use the new interface. In all other cases we need to revert to use the old interface. --- src/HTTPDownload.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index dd4b55a537..3cb79184c9 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -343,6 +343,53 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() m_result = HTTP_Skipped; } else if (response_code == 200) { // "OK" m_result = HTTP_Success; + /* TRANSLATORS: parameters are 'size transferred', 'URL' and 'download time' */ + CFormat message(_("HTTP: Downloaded %s from '%s' in %s")); + curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); + + // get downloaded size +#if LIBCURL_VERSION_NUM >= 0x073700 + /* CURLINFO_SIZE_DOWNLOAD_T was introduced in 7.55.0 */ + /* check the runtime version, too */ + if (data->version_num >= 0x073700) { + curl_off_t dl; + curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl); + message % CastItoXBytes(dl); + } else +#endif + { + double dl; + curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl); + message % CastItoXBytes((uint64)dl); + } + + // get effective URL + { + char *url = NULL; + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); + message % wxString(url); + } + + // get download time +#if LIBCURL_VERSION_NUM >= 0x073d00 + /* In libcurl 7.61.0, support was added for extracting the time in plain + microseconds. Older libcurl versions are stuck in using 'double' for this + information. */ + if (data->version_num >= 0x073d00) { + curl_off_t tm; + curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &tm); + // CastSecondsToHM() uses milliseconds while we have microseconds now + message % CastSecondsToHM(tm / 1000000, (tm / 1000) % 1000); + } else +#endif + { + double tm; + curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &tm); + message % CastSecondsToHM((uint32)tm, (uint16)(tm * 1000)); + } + + // Summarize transfer details + AddLogLineN(message); } else { m_result = HTTP_Error; } From 26899d769d39db0fc497648f03d0f617d437e668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Thu, 1 Oct 2020 18:04:15 +0200 Subject: [PATCH 08/10] curl: Add proxy support --- src/HTTPDownload.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index 3cb79184c9..ade0111b20 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -319,6 +319,47 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl_easy_setopt(curl, CURLOPT_INTERFACE, (const char *)unicode2char(thePrefs::GetAddress())); } + // proxy + if (use_proxy) { + switch (proxy_data->m_proxyType) { + case PROXY_SOCKS5: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); +#if LIBCURL_VERSION_NUM >= 0x073700 + // CURLOPT_SOCKS5_AUTH was added in 7.55.0 + if (proxy_data->m_enablePassword) { + curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, CURLAUTH_BASIC); + } else { + curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, CURLAUTH_NONE); + } +#endif + break; + case PROXY_SOCKS4: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); + break; + case PROXY_HTTP: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + // Using only "Basic" authentication as the rest of the code + // (in Proxy.cpp) supports only that + curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + // Not tunneling through the proxy on purpose, let it cache + // HTTP traffic if possible (this is the default behaviour). + //curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 0L); + break; + case PROXY_SOCKS4a: + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A); + break; + default: + goto noProxy; + } + curl_easy_setopt(curl, CURLOPT_PROXY, (const char *)unicode2char(proxy_data->m_proxyHostName)); + curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy_data->m_proxyPort); + if (proxy_data->m_enablePassword) { + curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, (const char *)unicode2char(proxy_data->m_userName)); + curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, (const char *)unicode2char(proxy_data->m_password)); + } + } +noProxy: + // perform the action res = curl_easy_perform(curl); From 34a2941a4386b01842631dd2f2ca2f43a8041a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Mon, 12 Oct 2020 04:02:33 +0200 Subject: [PATCH 09/10] curl: Added support for cancelling an ongoing transfer We use the progress callback to periodically check whether the current download is requested to be cancelled (i.e. the user pressed the 'Cancel' button, or the application is exiting). That requires that we always have a progress callback installed, therefore the minimum required libcurl version is lowered to 7.19.1. --- configure.ac | 2 +- src/HTTPDownload.cpp | 64 ++++++++++++++++++++++++++++---------------- src/HTTPDownload.h | 2 ++ 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 7d15129f8b..23057ac00c 100644 --- a/configure.ac +++ b/configure.ac @@ -234,7 +234,7 @@ MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui, fileview], # Check for libcurl MULE_IF_ENABLED_ANY([monolithic, amule-daemon, amule-gui], -[LIBCURL_CHECK_CONFIG(, [7.32.0],, [MULE_WARNING([libcurl not found or disabled. Reverting to using wxHTTP for http download, but beware, https won't be supported.])])]) +[LIBCURL_CHECK_CONFIG(, [7.19.1],, [MULE_WARNING([libcurl not found or disabled. Reverting to using wxHTTP for http download, but beware, https won't be supported.])])]) MULE_COMPILATION_FLAGS diff --git a/src/HTTPDownload.cpp b/src/HTTPDownload.cpp index ade0111b20..b69b9709cc 100644 --- a/src/HTTPDownload.cpp +++ b/src/HTTPDownload.cpp @@ -31,6 +31,7 @@ #ifdef HAVE_LIBCURL # include # include // Needed for the VERSION_ defines +# include // Needed for GUI_ONLY() #else # include #endif @@ -216,19 +217,31 @@ int mule_curl_debug_callback(CURL* WXUNUSED(handle), curl_infotype type, char *d } #endif -#ifndef AMULE_DAEMON -int mule_curl_xferinfo_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t WXUNUSED(ultotal), curl_off_t WXUNUSED(ulnow)) +int mule_curl_xferinfo_callback(void *clientp, curl_off_t GUI_ONLY(dltotal), curl_off_t GUI_ONLY(dlnow), curl_off_t WXUNUSED(ultotal), curl_off_t WXUNUSED(ulnow)) { - wxEvtHandler *dialog = static_cast(clientp); + CHTTPDownloadThread *thread = static_cast(clientp); + + if (thread->TestDestroy()) { + // returning nonzero will abort the current transfer + return 1; + } - CMuleInternalEvent evt(wxEVT_HTTP_PROGRESS); - evt.SetInt(dlnow); - evt.SetExtraLong(dltotal); - wxPostEvent(dialog, evt); +#ifndef AMULE_DAEMON + if (thread->GetProgressDialog()) { + CMuleInternalEvent evt(wxEVT_HTTP_PROGRESS); + evt.SetInt(dlnow); + evt.SetExtraLong(dltotal); + wxPostEvent(thread->GetProgressDialog(), evt); + } +#endif return 0; } -#endif + +int mule_curl_progress_callback(void *clientp, double dltotal, double dlnow, double WXUNUSED(ultotal), double WXUNUSED(ulnow)) +{ + return mule_curl_xferinfo_callback(clientp, (curl_off_t)dltotal, (curl_off_t)dlnow, 0, 0); +} #endif /* HAVE_LIBCURL */ @@ -242,6 +255,7 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() #ifdef HAVE_LIBCURL CURL *curl; CURLcode res; + static unsigned int curl_version = 0; #else wxHTTP* url_handler = NULL; #endif @@ -265,6 +279,10 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() #ifdef HAVE_LIBCURL + if (curl_version == 0) { + curl_version = curl_version_info(CURLVERSION_NOW)->version_num; + } + curl = curl_easy_init(); if (curl) { struct curl_slist *list = NULL; @@ -284,20 +302,21 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif -#ifndef AMULE_DAEMON // show download progress - if (m_companion) { - // CURLOPT_XFERINFOFUNCTION was introduced in 7.32.0. - // We're not planning to support older libcurl versions, thus if - // the runtime library doesn't support CURLOPT_XFERINFOFUNCTION - // (probably because it's too old) we simply won't have a progress meter. - res = curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, mule_curl_xferinfo_callback); - if (res == CURLE_OK) { - curl_easy_setopt(curl, CURLOPT_XFERINFODATA, m_companion); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); - } - } + // This callback is used to cancel an ongoing transfer. +#if LIBCURL_VERSION_NUM >= 0x072000 + // CURLOPT_XFERINFOFUNCTION was introduced in 7.32.0. + if (curl_version >= 0x072000) { + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, mule_curl_xferinfo_callback); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this); + } else #endif + { + // CURLOPT_PROGRESSFUNCTION is deprecated in favour of CURLOPT_XFERINFOFUNCTION + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, mule_curl_progress_callback); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this); + } + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); // Build a conditional get request if the last modified date of the file being updated is known if (m_lastmodified.IsValid()) { @@ -386,13 +405,12 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() m_result = HTTP_Success; /* TRANSLATORS: parameters are 'size transferred', 'URL' and 'download time' */ CFormat message(_("HTTP: Downloaded %s from '%s' in %s")); - curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); // get downloaded size #if LIBCURL_VERSION_NUM >= 0x073700 /* CURLINFO_SIZE_DOWNLOAD_T was introduced in 7.55.0 */ /* check the runtime version, too */ - if (data->version_num >= 0x073700) { + if (curl_version >= 0x073700) { curl_off_t dl; curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl); message % CastItoXBytes(dl); @@ -416,7 +434,7 @@ CMuleThread::ExitCode CHTTPDownloadThread::Entry() /* In libcurl 7.61.0, support was added for extracting the time in plain microseconds. Older libcurl versions are stuck in using 'double' for this information. */ - if (data->version_num >= 0x073d00) { + if (curl_version >= 0x073d00) { curl_off_t tm; curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &tm); // CastSecondsToHM() uses milliseconds while we have microseconds now diff --git a/src/HTTPDownload.h b/src/HTTPDownload.h index 73740f5e28..859deca433 100644 --- a/src/HTTPDownload.h +++ b/src/HTTPDownload.h @@ -50,6 +50,8 @@ class CHTTPDownloadThread : public CMuleThread bool showDialog, bool checkDownloadNewer); static void StopAll(); + wxEvtHandler * GetProgressDialog() const { return m_companion; } + private: ExitCode Entry(); virtual void OnExit(); From 71e56dde907bbaee2c82e9c3470b733eff325658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9vai=20Tam=C3=A1s?= Date: Thu, 29 Oct 2020 10:34:04 +0100 Subject: [PATCH 10/10] Add libcurl to the debian build dependencies --- debian/changelog | 7 +++++++ debian/control | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 1478773d56..bb28e595b8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +amule (2.3.2+git-20201029) stable; urgency=low + + * git-rev: 34a2941 + 1 + * added libcurl dependency + + -- Dévai Tamás Thu, 29 Oct 2020 10:30:02 +0100 + amule (2.3.2+git-20191216) stable; urgency=low * git-rev: d157fe8 + 1 diff --git a/debian/control b/debian/control index d753005c43..7834ae7013 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: amule Section: net Priority: optional Maintainer: Werner Mahr (Vollstrecker) -Build-Depends: debhelper (>= 10), libglib2.0-dev, zlib1g-dev, libwxgtk3.0-dev, libgd2-xpm-dev | libgdchart-gd2-xpm-dev, bison, flex, libcrypto++-dev, libreadline-dev, libgeoip-dev, libupnp-dev (>> 1.6.6), binutils-dev, autoconf, libqt4-dev, kdelibs5-dev, gettext, libasio-dev +Build-Depends: debhelper (>= 10), libglib2.0-dev, zlib1g-dev, libwxgtk3.0-dev, libgd2-xpm-dev | libgdchart-gd2-xpm-dev, bison, flex, libcrypto++-dev, libreadline-dev, libgeoip-dev, libupnp-dev (>> 1.6.6), binutils-dev, autoconf, libqt4-dev, kdelibs5-dev, gettext, libasio-dev, libcurl-dev | libcurl4-openssl-dev (>= 7.19.1) Standards-Version: 3.9.1 Homepage: http://www.amule.org