16#include <zypp-core/fs/PathInfo.h>
17#include <zypp-core/Pathname.h>
18#include <zypp-core/base/LogTools.h>
19#include <zypp-core/base/String.h>
20#include <zypp-core/base/StringV.h>
21#include <zypp-curl/ProxyInfo>
22#include <zypp-curl/auth/CurlAuthData>
23#include <zypp-media/MediaException>
27#define TRANSFER_TIMEOUT_MAX 60 * 60
38 static const long ret = [](){
39 const char * env = getenv(
"ZYPP_MEDIA_CURL_DEBUG");
40 return env && *env ? str::strtonum<ulong>( env ) : 0;
49 if (
const char * envp = getenv(
"ZYPP_MEDIA_CURL_IPRESOLVE" ) ) {
50 WAR <<
"env set: $ZYPP_MEDIA_CURL_IPRESOLVE='" << envp <<
"'" << std::endl;
51 if ( strcmp( envp,
"4" ) == 0 ) ret = 4;
52 else if ( strcmp( envp,
"6" ) == 0 ) ret = 6;
67 static bool once __attribute__ ((__unused__)) = ( [] {
68 MIL <<
"global_init libcurl: " << curl_version_info(CURLVERSION_NOW)->version << endl;
69 if ( curl_global_init( CURL_GLOBAL_ALL ) != 0 )
70 WAR <<
"curl global init failed" << std::endl;
74int log_curl( CURL * curl, curl_infotype info,
char * ptr,
size_t len,
void * max_lvl )
76 if ( max_lvl ==
nullptr )
79 long maxlvl = *((
long *)max_lvl);
80 const char * pfx =
"";
81 bool isContent =
true;
84 case CURLINFO_TEXT:
if ( maxlvl < 1 )
return 0; pfx =
"*";
break;
85 case CURLINFO_HEADER_IN:
if ( maxlvl < 2 )
return 0; pfx =
"<";
break;
86 case CURLINFO_HEADER_OUT:
if ( maxlvl < 2 )
return 0; pfx =
">";
break;
87 case CURLINFO_SSL_DATA_IN:
if ( maxlvl < 3 )
return 0; isContent =
false; pfx =
"<[SSL]";
break;
88 case CURLINFO_SSL_DATA_OUT:
if ( maxlvl < 3 )
return 0; isContent =
false; pfx =
">[SSL]";
break;
89 case CURLINFO_DATA_IN:
if ( maxlvl < 3 )
return 0; isContent =
false; pfx =
"<[DTA]";
break;
90 case CURLINFO_DATA_OUT:
if ( maxlvl < 3 )
return 0; isContent =
false; pfx =
">[DTA]";
break;
99 std::vector<std::string_view> lines;
100 strv::split( std::string_view( ptr, len ),
"\n", [&lines]( std::string_view line,
unsigned,
bool last ) {
102 line = strv::rtrim( line,
"\r" );
103 lines.push_back( line );
105 for (
const auto & line : lines ) {
107 std::string_view::size_type pos { line.find(
" ", 15 ) };
108 if ( pos == std::string::npos )
110 DBG << curl <<
" " << pfx <<
" " << line.substr( 0, pos ) <<
" <credentials removed>" << endl;
113 DBG << curl <<
" " << pfx <<
" " << line << endl;
117 DBG << curl <<
" " << pfx <<
" " << len <<
" byte" << endl;
119 hexdumpOn(
DBG << curl <<
" " << pfx <<
" ", ptr, len );
127 INT <<
"Got a NULL curl handle" << endl;
131 curl_easy_setopt( curl, CURLOPT_VERBOSE, 1L );
132 curl_easy_setopt( curl, CURLOPT_DEBUGFUNCTION,
log_curl );
141 char * lstart = ptr, * lend = ptr;
143 size_t max = size * nmemb;
144 while (pos + 1 < max)
147 for (lstart = lend; *lend !=
'\n' && pos < max; ++lend, ++pos);
150 if ( strncasecmp( lstart,
"Location:", 9 ) == 0 )
152 std::string line { lstart, *(lend-1)==
'\r' ? lend-1 : lend };
153 DBG <<
"redirecting to " << line << std::endl;
155 *
reinterpret_cast<std::string *
>( userdata ) = line;
181 if( ! param.empty() )
183 long num = str::strtonum<long>(param);
190 if ( ! param.empty() )
194 if ( ! param.empty() )
209 const std::string & verify { url.
getQueryParam(
"ssl_verify") };
210 if( verify.empty() || verify ==
"yes" )
215 else if ( verify ==
"no" )
222 std::vector<std::string> flags;
223 str::split( verify, std::back_inserter(flags),
"," );
224 for (
const auto & flag : flags )
226 if ( flag ==
"host" )
228 else if ( flag ==
"peer" )
237 if( ! ca_path.empty() )
239 if( !
PathInfo(ca_path).isDir() || ! ca_path.absolute() )
247 if( ! client_cert.empty() )
249 if( !
PathInfo(client_cert).isFile() || ! client_cert.absolute() )
257 if( ! client_key.empty() )
259 if( !
PathInfo(client_key).isFile() || ! client_key.absolute() )
267 if ( ! param.empty() )
278 const std::string & proxyport { url.
getQueryParam(
"proxyport" ) };
279 if ( ! proxyport.empty() ) {
290 if ( ! param.empty() )
307 DBG <<
"Rethrowing as MediaUnauthorizedException.";
315 const std::string & param { url.
getQueryParam(
"head_requests") };
316 if( ! param.empty() && param ==
"no" )
348 const char char_r,
const std::string & escaped_r ) {
349 for ( std::string::size_type pos = str_r.find( char_r );
350 pos != std::string::npos; pos = str_r.find( char_r, pos ) ) {
351 str_r.replace( pos, 1, escaped_r );
361 char * tmp = curl_unescape( text_r.c_str(), 0 );
362 std::string ret( tmp );
396 using namespace std::literals::string_literals;
397 for (
const std::string ¶m : {
"proxy"s,
"proxyport"s,
"proxyuser"s,
"proxypass"s,
"ssl_capath"s,
"ssl_verify"s } )
399 const std::string & value( template_r.
getQueryParam( param ) );
400 if ( ! value.empty() )
Provides API related macros.
const std::string & msg() const
Return the message string provided to the ctor.
std::string getScheme() const
Returns the scheme name of the URL.
std::string asString() const
Returns a default string representation of the Url object.
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
void setFragment(const std::string &fragment, EEncoding eflag=zypp::url::E_DECODED)
Set the fragment string in the URL.
std::string getQueryParam(const std::string ¶m, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
void delQueryParam(const std::string ¶m)
remove the specified query parameter.
void setPassword(const std::string &pass, EEncoding eflag=zypp::url::E_DECODED)
Set the password in the URL authority.
void setPathParams(const std::string ¶ms)
Set the path parameters.
void setQueryParam(const std::string ¶m, const std::string &value)
Set or add value for the specified query parameter.
void setUsername(const std::string &user, EEncoding eflag=zypp::url::E_DECODED)
Set the username in the URL authority.
std::string getPassword(EEncoding eflag=zypp::url::E_DECODED) const
Returns the password from the URL authority.
Wrapper class for stat/lstat.
#define TRANSFER_TIMEOUT_MAX
#define EXPLICITLY_NO_PROXY
void fillSettingsFromUrl(const Url &url, media::TransferSettings &s)
Fills the settings structure using options passed on the url for example ?timeout=x&proxy=foo.
size_t log_redirects_curl(char *ptr, size_t size, size_t nmemb, void *userdata)
void globalInitCurlOnce()
zypp::Url propagateQueryParams(zypp::Url url_r, const zypp::Url &template_r)
std::string curlUnEscape(std::string text_r)
void setupZYPP_MEDIA_CURL_DEBUG(CURL *curl)
Setup CURLOPT_VERBOSE and CURLOPT_DEBUGFUNCTION according to env::ZYPP_MEDIA_CURL_DEBUG.
std::string curlEscapedPath(std::string path_r)
void fillSettingsSystemProxy(const Url &url, media::TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Url clearQueryString(const Url &url)
void curlEscape(std::string &str_r, const char char_r, const std::string &escaped_r)
int log_curl(CURL *curl, curl_infotype info, char *ptr, size_t len, void *max_lvl)
const long & ZYPP_MEDIA_CURL_DEBUG()
const long& for setting CURLOPT_DEBUGDATA Returns a reference to a static variable,...
int ZYPP_MEDIA_CURL_IPRESOLVE()
4/6 to force IPv4/v6
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", const Trim trim_r=NO_TRIM)
Split line_r into words.
@ E_ENCODED
Flag to request encoded string(s).
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & hexdumpOn(std::ostream &outs, const unsigned char *ptr, size_t size)
hexdump data on stream
static const ViewOption WITH_SCHEME
Option to include scheme name in the URL string.
static const ViewOption WITH_PORT
Option to include port number in the URL string.
static const ViewOption WITH_HOST
Option to include hostname in the URL string.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.