libzypp  16.20.4
MediaCurl.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <list>
15 
16 #include "zypp/base/Logger.h"
17 #include "zypp/ExternalProgram.h"
18 #include "zypp/base/String.h"
19 #include "zypp/base/Gettext.h"
20 #include "zypp/base/Sysconfig.h"
21 #include "zypp/base/Gettext.h"
22 
23 #include "zypp/media/MediaCurl.h"
24 #include "zypp/media/ProxyInfo.h"
27 #include "zypp/media/CurlConfig.h"
28 #include "zypp/thread/Once.h"
29 #include "zypp/Target.h"
30 #include "zypp/ZYppFactory.h"
31 #include "zypp/ZConfig.h"
32 
33 #include <cstdlib>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/mount.h>
37 #include <errno.h>
38 #include <dirent.h>
39 #include <unistd.h>
40 
41 #define DETECT_DIR_INDEX 0
42 #define CONNECT_TIMEOUT 60
43 #define TRANSFER_TIMEOUT_MAX 60 * 60
44 
45 #define EXPLICITLY_NO_PROXY "_none_"
46 
47 #undef CURLVERSION_AT_LEAST
48 #define CURLVERSION_AT_LEAST(M,N,O) LIBCURL_VERSION_NUM >= ((((M)<<8)+(N))<<8)+(O)
49 
50 using namespace std;
51 using namespace zypp::base;
52 
53 namespace
54 {
55  zypp::thread::OnceFlag g_InitOnceFlag = PTHREAD_ONCE_INIT;
56  zypp::thread::OnceFlag g_FreeOnceFlag = PTHREAD_ONCE_INIT;
57 
58  extern "C" void _do_free_once()
59  {
60  curl_global_cleanup();
61  }
62 
63  extern "C" void globalFreeOnce()
64  {
65  zypp::thread::callOnce(g_FreeOnceFlag, _do_free_once);
66  }
67 
68  extern "C" void _do_init_once()
69  {
70  CURLcode ret = curl_global_init( CURL_GLOBAL_ALL );
71  if ( ret != 0 )
72  {
73  WAR << "curl global init failed" << endl;
74  }
75 
76  //
77  // register at exit handler ?
78  // this may cause trouble, because we can protect it
79  // against ourself only.
80  // if the app sets an atexit handler as well, it will
81  // cause a double free while the second of them runs.
82  //
83  //std::atexit( globalFreeOnce);
84  }
85 
86  inline void globalInitOnce()
87  {
88  zypp::thread::callOnce(g_InitOnceFlag, _do_init_once);
89  }
90 
91  int log_curl(CURL *curl, curl_infotype info,
92  char *ptr, size_t len, void *max_lvl)
93  {
94  std::string pfx(" ");
95  long lvl = 0;
96  switch( info)
97  {
98  case CURLINFO_TEXT: lvl = 1; pfx = "*"; break;
99  case CURLINFO_HEADER_IN: lvl = 2; pfx = "<"; break;
100  case CURLINFO_HEADER_OUT: lvl = 2; pfx = ">"; break;
101  default: break;
102  }
103  if( lvl > 0 && max_lvl != NULL && lvl <= *((long *)max_lvl))
104  {
105  std::string msg(ptr, len);
106  std::list<std::string> lines;
107  std::list<std::string>::const_iterator line;
108  zypp::str::split(msg, std::back_inserter(lines), "\r\n");
109  for(line = lines.begin(); line != lines.end(); ++line)
110  {
111  DBG << pfx << " " << *line << endl;
112  }
113  }
114  return 0;
115  }
116 
117  static size_t
118  log_redirects_curl(
119  void *ptr, size_t size, size_t nmemb, void *stream)
120  {
121  // INT << "got header: " << string((char *)ptr, ((char*)ptr) + size*nmemb) << endl;
122 
123  char * lstart = (char *)ptr, * lend = (char *)ptr;
124  size_t pos = 0;
125  size_t max = size * nmemb;
126  while (pos + 1 < max)
127  {
128  // get line
129  for (lstart = lend; *lend != '\n' && pos < max; ++lend, ++pos);
130 
131  // look for "Location"
132  string line(lstart, lend);
133  if (line.find("Location") != string::npos)
134  {
135  DBG << "redirecting to " << line << endl;
136  return max;
137  }
138 
139  // continue with the next line
140  if (pos + 1 < max)
141  {
142  ++lend;
143  ++pos;
144  }
145  else
146  break;
147  }
148 
149  return max;
150  }
151 }
152 
153 namespace zypp {
154 
156  namespace env
157  {
158  namespace
159  {
160  inline int getZYPP_MEDIA_CURL_IPRESOLVE()
161  {
162  int ret = 0;
163  if ( const char * envp = getenv( "ZYPP_MEDIA_CURL_IPRESOLVE" ) )
164  {
165  WAR << "env set: $ZYPP_MEDIA_CURL_IPRESOLVE='" << envp << "'" << endl;
166  if ( strcmp( envp, "4" ) == 0 ) ret = 4;
167  else if ( strcmp( envp, "6" ) == 0 ) ret = 6;
168  }
169  return ret;
170  }
171  }
172 
174  {
175  static int _v = getZYPP_MEDIA_CURL_IPRESOLVE();
176  return _v;
177  }
178  } // namespace env
180 
181  namespace media {
182 
183  namespace {
184  struct ProgressData
185  {
186  ProgressData( CURL *_curl, time_t _timeout = 0, const Url & _url = Url(),
187  ByteCount expectedFileSize_r = 0,
188  callback::SendReport<DownloadProgressReport> *_report = nullptr )
189  : curl( _curl )
190  , url( _url )
191  , timeout( _timeout )
192  , reached( false )
193  , fileSizeExceeded ( false )
194  , report( _report )
195  , _expectedFileSize( expectedFileSize_r )
196  {}
197 
198  CURL *curl;
199  Url url;
200  time_t timeout;
201  bool reached;
203  callback::SendReport<DownloadProgressReport> *report;
204  ByteCount _expectedFileSize;
205 
206  time_t _timeStart = 0;
207  time_t _timeLast = 0;
208  time_t _timeRcv = 0;
209  time_t _timeNow = 0;
210 
211  double _dnlTotal = 0.0;
212  double _dnlLast = 0.0;
213  double _dnlNow = 0.0;
214 
215  int _dnlPercent= 0;
216 
217  double _drateTotal= 0.0;
218  double _drateLast = 0.0;
219 
220  void updateStats( double dltotal = 0.0, double dlnow = 0.0 )
221  {
222  time_t now = _timeNow = time(0);
223 
224  // If called without args (0.0), recompute based on the last values seen
225  if ( dltotal && dltotal != _dnlTotal )
226  _dnlTotal = dltotal;
227 
228  if ( dlnow && dlnow != _dnlNow )
229  {
230  _timeRcv = now;
231  _dnlNow = dlnow;
232  }
233  else if ( !_dnlNow && !_dnlTotal )
234  {
235  // Start time counting as soon as first data arrives.
236  // Skip the connection / redirection time at begin.
237  return;
238  }
239 
240  // init or reset if time jumps back
241  if ( !_timeStart || _timeStart > now )
242  _timeStart = _timeLast = _timeRcv = now;
243 
244  // timeout condition
245  if ( timeout )
246  reached = ( (now - _timeRcv) > timeout );
247 
248  // check if the downloaded data is already bigger than what we expected
249  fileSizeExceeded = _expectedFileSize > 0 && _expectedFileSize < static_cast<ByteCount::SizeType>(_dnlNow);
250 
251  // percentage:
252  if ( _dnlTotal )
253  _dnlPercent = int(_dnlNow * 100 / _dnlTotal);
254 
255  // download rates:
256  _drateTotal = _dnlNow / std::max( int(now - _timeStart), 1 );
257 
258  if ( _timeLast < now )
259  {
260  _drateLast = (_dnlNow - _dnlLast) / int(now - _timeLast);
261  // start new period
262  _timeLast = now;
263  _dnlLast = _dnlNow;
264  }
265  else if ( _timeStart == _timeLast )
267  }
268 
269  int reportProgress() const
270  {
271  if ( fileSizeExceeded )
272  return 1;
273  if ( reached )
274  return 1; // no-data timeout
275  if ( report && !(*report)->progress( _dnlPercent, url, _drateTotal, _drateLast ) )
276  return 1; // user requested abort
277  return 0;
278  }
279 
280 
281  // download rate of the last period (cca 1 sec)
282  double drate_period;
283  // bytes downloaded at the start of the last period
284  double dload_period;
285  // seconds from the start of the download
286  long secs;
287  // average download rate
288  double drate_avg;
289  // last time the progress was reported
290  time_t ltime;
291  // bytes downloaded at the moment the progress was last reported
292  double dload;
293  // bytes uploaded at the moment the progress was last reported
294  double uload;
295  };
296 
298 
299  inline void escape( string & str_r,
300  const char char_r, const string & escaped_r ) {
301  for ( string::size_type pos = str_r.find( char_r );
302  pos != string::npos; pos = str_r.find( char_r, pos ) ) {
303  str_r.replace( pos, 1, escaped_r );
304  }
305  }
306 
307  inline string escapedPath( string path_r ) {
308  escape( path_r, ' ', "%20" );
309  return path_r;
310  }
311 
312  inline string unEscape( string text_r ) {
313  char * tmp = curl_unescape( text_r.c_str(), 0 );
314  string ret( tmp );
315  curl_free( tmp );
316  return ret;
317  }
318 
319  }
320 
326 {
327  std::string param(url.getQueryParam("timeout"));
328  if( !param.empty())
329  {
330  long num = str::strtonum<long>(param);
331  if( num >= 0 && num <= TRANSFER_TIMEOUT_MAX)
332  s.setTimeout(num);
333  }
334 
335  if ( ! url.getUsername().empty() )
336  {
337  s.setUsername(url.getUsername());
338  if ( url.getPassword().size() )
339  s.setPassword(url.getPassword());
340  }
341  else
342  {
343  // if there is no username, set anonymous auth
344  if ( ( url.getScheme() == "ftp" || url.getScheme() == "tftp" ) && s.username().empty() )
345  s.setAnonymousAuth();
346  }
347 
348  if ( url.getScheme() == "https" )
349  {
350  s.setVerifyPeerEnabled(false);
351  s.setVerifyHostEnabled(false);
352 
353  std::string verify( url.getQueryParam("ssl_verify"));
354  if( verify.empty() ||
355  verify == "yes")
356  {
357  s.setVerifyPeerEnabled(true);
358  s.setVerifyHostEnabled(true);
359  }
360  else if( verify == "no")
361  {
362  s.setVerifyPeerEnabled(false);
363  s.setVerifyHostEnabled(false);
364  }
365  else
366  {
367  std::vector<std::string> flags;
368  std::vector<std::string>::const_iterator flag;
369  str::split( verify, std::back_inserter(flags), ",");
370  for(flag = flags.begin(); flag != flags.end(); ++flag)
371  {
372  if( *flag == "host")
373  s.setVerifyHostEnabled(true);
374  else if( *flag == "peer")
375  s.setVerifyPeerEnabled(true);
376  else
377  ZYPP_THROW(MediaBadUrlException(url, "Unknown ssl_verify flag"));
378  }
379  }
380  }
381 
382  Pathname ca_path( url.getQueryParam("ssl_capath") );
383  if( ! ca_path.empty())
384  {
385  if( !PathInfo(ca_path).isDir() || ! ca_path.absolute())
386  ZYPP_THROW(MediaBadUrlException(url, "Invalid ssl_capath path"));
387  else
389  }
390 
391  Pathname client_cert( url.getQueryParam("ssl_clientcert") );
392  if( ! client_cert.empty())
393  {
394  if( !PathInfo(client_cert).isFile() || !client_cert.absolute())
395  ZYPP_THROW(MediaBadUrlException(url, "Invalid ssl_clientcert file"));
396  else
397  s.setClientCertificatePath(client_cert);
398  }
399  Pathname client_key( url.getQueryParam("ssl_clientkey") );
400  if( ! client_key.empty())
401  {
402  if( !PathInfo(client_key).isFile() || !client_key.absolute())
403  ZYPP_THROW(MediaBadUrlException(url, "Invalid ssl_clientkey file"));
404  else
405  s.setClientKeyPath(client_key);
406  }
407 
408  param = url.getQueryParam( "proxy" );
409  if ( ! param.empty() )
410  {
411  if ( param == EXPLICITLY_NO_PROXY ) {
412  // Workaround TransferSettings shortcoming: With an
413  // empty proxy string, code will continue to look for
414  // valid proxy settings. So set proxy to some non-empty
415  // string, to indicate it has been explicitly disabled.
417  s.setProxyEnabled(false);
418  }
419  else {
420  string proxyport( url.getQueryParam( "proxyport" ) );
421  if ( ! proxyport.empty() ) {
422  param += ":" + proxyport;
423  }
424  s.setProxy(param);
425  s.setProxyEnabled(true);
426  }
427  }
428 
429  param = url.getQueryParam( "proxyuser" );
430  if ( ! param.empty() )
431  {
432  s.setProxyUsername(param);
433  s.setProxyPassword(url.getQueryParam( "proxypass" ));
434  }
435 
436  // HTTP authentication type
437  param = url.getQueryParam("auth");
438  if (!param.empty() && (url.getScheme() == "http" || url.getScheme() == "https"))
439  {
440  try
441  {
442  CurlAuthData::auth_type_str2long(param); // check if we know it
443  }
444  catch (MediaException & ex_r)
445  {
446  DBG << "Rethrowing as MediaUnauthorizedException.";
447  ZYPP_THROW(MediaUnauthorizedException(url, ex_r.msg(), "", ""));
448  }
449  s.setAuthType(param);
450  }
451 
452  // workarounds
453  param = url.getQueryParam("head_requests");
454  if( !param.empty() && param == "no" )
455  s.setHeadRequestsAllowed(false);
456 }
457 
463 {
464  ProxyInfo proxy_info;
465  if ( proxy_info.useProxyFor( url ) )
466  {
467  // We must extract any 'user:pass' from the proxy url
468  // otherwise they won't make it into curl (.curlrc wins).
469  try {
470  Url u( proxy_info.proxy( url ) );
471  s.setProxy( u.asString( url::ViewOption::WITH_SCHEME + url::ViewOption::WITH_HOST + url::ViewOption::WITH_PORT ) );
472  // don't overwrite explicit auth settings
473  if ( s.proxyUsername().empty() )
474  {
477  }
478  s.setProxyEnabled( true );
479  }
480  catch (...) {} // no proxy if URL is malformed
481  }
482 }
483 
484 Pathname MediaCurl::_cookieFile = "/var/lib/YaST2/cookies";
485 
490 static const char *const anonymousIdHeader()
491 {
492  // we need to add the release and identifier to the
493  // agent string.
494  // The target could be not initialized, and then this information
495  // is guessed.
496  static const std::string _value(
498  "X-ZYpp-AnonymousId: %s",
499  Target::anonymousUniqueId( Pathname()/*guess root*/ ).c_str() ) )
500  );
501  return _value.c_str();
502 }
503 
508 static const char *const distributionFlavorHeader()
509 {
510  // we need to add the release and identifier to the
511  // agent string.
512  // The target could be not initialized, and then this information
513  // is guessed.
514  static const std::string _value(
516  "X-ZYpp-DistributionFlavor: %s",
517  Target::distributionFlavor( Pathname()/*guess root*/ ).c_str() ) )
518  );
519  return _value.c_str();
520 }
521 
526 static const char *const agentString()
527 {
528  // we need to add the release and identifier to the
529  // agent string.
530  // The target could be not initialized, and then this information
531  // is guessed.
532  static const std::string _value(
533  str::form(
534  "ZYpp %s (curl %s) %s"
535  , VERSION
536  , curl_version_info(CURLVERSION_NOW)->version
537  , Target::targetDistribution( Pathname()/*guess root*/ ).c_str()
538  )
539  );
540  return _value.c_str();
541 }
542 
543 // we use this define to unbloat code as this C setting option
544 // and catching exception is done frequently.
546 #define SET_OPTION(opt,val) do { \
547  ret = curl_easy_setopt ( _curl, opt, val ); \
548  if ( ret != 0) { \
549  ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); \
550  } \
551  } while ( false )
552 
553 #define SET_OPTION_OFFT(opt,val) SET_OPTION(opt,(curl_off_t)val)
554 #define SET_OPTION_LONG(opt,val) SET_OPTION(opt,(long)val)
555 #define SET_OPTION_VOID(opt,val) SET_OPTION(opt,(void*)val)
556 
557 MediaCurl::MediaCurl( const Url & url_r,
558  const Pathname & attach_point_hint_r )
559  : MediaHandler( url_r, attach_point_hint_r,
560  "/", // urlpath at attachpoint
561  true ), // does_download
562  _curl( NULL ),
563  _customHeaders(0L)
564 {
565  _curlError[0] = '\0';
566  _curlDebug = 0L;
567 
568  MIL << "MediaCurl::MediaCurl(" << url_r << ", " << attach_point_hint_r << ")" << endl;
569 
570  globalInitOnce();
571 
572  if( !attachPoint().empty())
573  {
574  PathInfo ainfo(attachPoint());
575  Pathname apath(attachPoint() + "XXXXXX");
576  char *atemp = ::strdup( apath.asString().c_str());
577  char *atest = NULL;
578  if( !ainfo.isDir() || !ainfo.userMayRWX() ||
579  atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
580  {
581  WAR << "attach point " << ainfo.path()
582  << " is not useable for " << url_r.getScheme() << endl;
583  setAttachPoint("", true);
584  }
585  else if( atest != NULL)
586  ::rmdir(atest);
587 
588  if( atemp != NULL)
589  ::free(atemp);
590  }
591 }
592 
594 {
595  Url curlUrl (url);
596  curlUrl.setUsername( "" );
597  curlUrl.setPassword( "" );
598  curlUrl.setPathParams( "" );
599  curlUrl.setFragment( "" );
600  curlUrl.delQueryParam("cookies");
601  curlUrl.delQueryParam("proxy");
602  curlUrl.delQueryParam("proxyport");
603  curlUrl.delQueryParam("proxyuser");
604  curlUrl.delQueryParam("proxypass");
605  curlUrl.delQueryParam("ssl_capath");
606  curlUrl.delQueryParam("ssl_verify");
607  curlUrl.delQueryParam("ssl_clientcert");
608  curlUrl.delQueryParam("timeout");
609  curlUrl.delQueryParam("auth");
610  curlUrl.delQueryParam("username");
611  curlUrl.delQueryParam("password");
612  curlUrl.delQueryParam("mediahandler");
613  curlUrl.delQueryParam("credentials");
614  curlUrl.delQueryParam("head_requests");
615  return curlUrl;
616 }
617 
619 {
620  return _settings;
621 }
622 
623 
624 void MediaCurl::setCookieFile( const Pathname &fileName )
625 {
626  _cookieFile = fileName;
627 }
628 
630 
631 void MediaCurl::checkProtocol(const Url &url) const
632 {
633  curl_version_info_data *curl_info = NULL;
634  curl_info = curl_version_info(CURLVERSION_NOW);
635  // curl_info does not need any free (is static)
636  if (curl_info->protocols)
637  {
638  const char * const *proto;
639  std::string scheme( url.getScheme());
640  bool found = false;
641  for(proto=curl_info->protocols; !found && *proto; ++proto)
642  {
643  if( scheme == std::string((const char *)*proto))
644  found = true;
645  }
646  if( !found)
647  {
648  std::string msg("Unsupported protocol '");
649  msg += scheme;
650  msg += "'";
652  }
653  }
654 }
655 
657 {
658  {
659  char *ptr = getenv("ZYPP_MEDIA_CURL_DEBUG");
660  _curlDebug = (ptr && *ptr) ? str::strtonum<long>( ptr) : 0L;
661  if( _curlDebug > 0)
662  {
663  curl_easy_setopt( _curl, CURLOPT_VERBOSE, 1L);
664  curl_easy_setopt( _curl, CURLOPT_DEBUGFUNCTION, log_curl);
665  curl_easy_setopt( _curl, CURLOPT_DEBUGDATA, &_curlDebug);
666  }
667  }
668 
669  curl_easy_setopt(_curl, CURLOPT_HEADERFUNCTION, log_redirects_curl);
670  CURLcode ret = curl_easy_setopt( _curl, CURLOPT_ERRORBUFFER, _curlError );
671  if ( ret != 0 ) {
672  ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer"));
673  }
674 
675  SET_OPTION(CURLOPT_FAILONERROR, 1L);
676  SET_OPTION(CURLOPT_NOSIGNAL, 1L);
677 
678  // create non persistant settings
679  // so that we don't add headers twice
680  TransferSettings vol_settings(_settings);
681 
682  // add custom headers for download.opensuse.org (bsc#955801)
683  if ( _url.getHost() == "download.opensuse.org" )
684  {
685  vol_settings.addHeader(anonymousIdHeader());
686  vol_settings.addHeader(distributionFlavorHeader());
687  }
688  vol_settings.addHeader("Pragma:");
689 
690  _settings.setTimeout(ZConfig::instance().download_transfer_timeout());
692 
694 
695  // fill some settings from url query parameters
696  try
697  {
699  }
700  catch ( const MediaException &e )
701  {
702  disconnectFrom();
703  ZYPP_RETHROW(e);
704  }
705  // if the proxy was not set (or explicitly unset) by url, then look...
706  if ( _settings.proxy().empty() )
707  {
708  // ...at the system proxy settings
710  }
711 
714  {
715  switch ( env::ZYPP_MEDIA_CURL_IPRESOLVE() )
716  {
717  case 4: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); break;
718  case 6: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); break;
719  }
720  }
721 
725  SET_OPTION(CURLOPT_CONNECTTIMEOUT, _settings.connectTimeout());
726  // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit
727  // just in case curl does not trigger its progress callback frequently
728  // enough.
729  if ( _settings.timeout() )
730  {
731  SET_OPTION(CURLOPT_TIMEOUT, 3600L);
732  }
733 
734  // follow any Location: header that the server sends as part of
735  // an HTTP header (#113275)
736  SET_OPTION(CURLOPT_FOLLOWLOCATION, 1L);
737  // 3 redirects seem to be too few in some cases (bnc #465532)
738  SET_OPTION(CURLOPT_MAXREDIRS, 6L);
739 
740  if ( _url.getScheme() == "https" )
741  {
742 #if CURLVERSION_AT_LEAST(7,19,4)
743  // restrict following of redirections from https to https only
744  SET_OPTION( CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS );
745 #endif
746 
749  {
751  }
752 
754  {
755  SET_OPTION(CURLOPT_SSLCERT, _settings.clientCertificatePath().c_str());
756  }
757  if( ! _settings.clientKeyPath().empty() )
758  {
759  SET_OPTION(CURLOPT_SSLKEY, _settings.clientKeyPath().c_str());
760  }
761 
762 #ifdef CURLSSLOPT_ALLOW_BEAST
763  // see bnc#779177
764  ret = curl_easy_setopt( _curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST );
765  if ( ret != 0 ) {
766  disconnectFrom();
768  }
769 #endif
770  SET_OPTION(CURLOPT_SSL_VERIFYPEER, _settings.verifyPeerEnabled() ? 1L : 0L);
771  SET_OPTION(CURLOPT_SSL_VERIFYHOST, _settings.verifyHostEnabled() ? 2L : 0L);
772  // bnc#903405 - POODLE: libzypp should only talk TLS
773  SET_OPTION(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
774  }
775 
776  SET_OPTION(CURLOPT_USERAGENT, _settings.userAgentString().c_str() );
777 
778  /*---------------------------------------------------------------*
779  CURLOPT_USERPWD: [user name]:[password]
780 
781  Url::username/password -> CURLOPT_USERPWD
782  If not provided, anonymous FTP identification
783  *---------------------------------------------------------------*/
784 
785  if ( _settings.userPassword().size() )
786  {
787  SET_OPTION(CURLOPT_USERPWD, _settings.userPassword().c_str());
788  string use_auth = _settings.authType();
789  if (use_auth.empty())
790  use_auth = "digest,basic"; // our default
791  long auth = CurlAuthData::auth_type_str2long(use_auth);
792  if( auth != CURLAUTH_NONE)
793  {
794  DBG << "Enabling HTTP authentication methods: " << use_auth
795  << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl;
796  SET_OPTION(CURLOPT_HTTPAUTH, auth);
797  }
798  }
799 
800  if ( _settings.proxyEnabled() && ! _settings.proxy().empty() )
801  {
802  DBG << "Proxy: '" << _settings.proxy() << "'" << endl;
803  SET_OPTION(CURLOPT_PROXY, _settings.proxy().c_str());
804  SET_OPTION(CURLOPT_PROXYAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST|CURLAUTH_NTLM );
805  /*---------------------------------------------------------------*
806  * CURLOPT_PROXYUSERPWD: [user name]:[password]
807  *
808  * Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD
809  * If not provided, $HOME/.curlrc is evaluated
810  *---------------------------------------------------------------*/
811 
812  string proxyuserpwd = _settings.proxyUserPassword();
813 
814  if ( proxyuserpwd.empty() )
815  {
816  CurlConfig curlconf;
817  CurlConfig::parseConfig(curlconf); // parse ~/.curlrc
818  if ( curlconf.proxyuserpwd.empty() )
819  DBG << "Proxy: ~/.curlrc does not contain the proxy-user option" << endl;
820  else
821  {
822  proxyuserpwd = curlconf.proxyuserpwd;
823  DBG << "Proxy: using proxy-user from ~/.curlrc" << endl;
824  }
825  }
826  else
827  {
828  DBG << "Proxy: using provided proxy-user '" << _settings.proxyUsername() << "'" << endl;
829  }
830 
831  if ( ! proxyuserpwd.empty() )
832  {
833  SET_OPTION(CURLOPT_PROXYUSERPWD, unEscape( proxyuserpwd ).c_str());
834  }
835  }
836 #if CURLVERSION_AT_LEAST(7,19,4)
837  else if ( _settings.proxy() == EXPLICITLY_NO_PROXY )
838  {
839  // Explicitly disabled in URL (see fillSettingsFromUrl()).
840  // This should also prevent libcurl from looking into the environment.
841  DBG << "Proxy: explicitly NOPROXY" << endl;
842  SET_OPTION(CURLOPT_NOPROXY, "*");
843  }
844 #endif
845  else
846  {
847  DBG << "Proxy: not explicitly set" << endl;
848  DBG << "Proxy: libcurl may look into the environment" << endl;
849  }
850 
852  if ( _settings.minDownloadSpeed() != 0 )
853  {
854  SET_OPTION(CURLOPT_LOW_SPEED_LIMIT, _settings.minDownloadSpeed());
855  // default to 10 seconds at low speed
856  SET_OPTION(CURLOPT_LOW_SPEED_TIME, 60L);
857  }
858 
859 #if CURLVERSION_AT_LEAST(7,15,5)
860  if ( _settings.maxDownloadSpeed() != 0 )
861  SET_OPTION_OFFT(CURLOPT_MAX_RECV_SPEED_LARGE, _settings.maxDownloadSpeed());
862 #endif
863 
864  /*---------------------------------------------------------------*
865  *---------------------------------------------------------------*/
866 
868  if ( str::strToBool( _url.getQueryParam( "cookies" ), true ) )
869  SET_OPTION(CURLOPT_COOKIEFILE, _currentCookieFile.c_str() );
870  else
871  MIL << "No cookies requested" << endl;
872  SET_OPTION(CURLOPT_COOKIEJAR, _currentCookieFile.c_str() );
873  SET_OPTION(CURLOPT_PROGRESSFUNCTION, &progressCallback );
874  SET_OPTION(CURLOPT_NOPROGRESS, 0L);
875 
876 #if CURLVERSION_AT_LEAST(7,18,0)
877  // bnc #306272
878  SET_OPTION(CURLOPT_PROXY_TRANSFER_MODE, 1L );
879 #endif
880  // append settings custom headers to curl
881  for ( TransferSettings::Headers::const_iterator it = vol_settings.headersBegin();
882  it != vol_settings.headersEnd();
883  ++it )
884  {
885  // MIL << "HEADER " << *it << std::endl;
886 
887  _customHeaders = curl_slist_append(_customHeaders, it->c_str());
888  if ( !_customHeaders )
890  }
891 
892  SET_OPTION(CURLOPT_HTTPHEADER, _customHeaders);
893 }
894 
896 
897 
898 void MediaCurl::attachTo (bool next)
899 {
900  if ( next )
902 
903  if ( !_url.isValid() )
905 
908  {
910  }
911 
912  disconnectFrom(); // clean _curl if needed
913  _curl = curl_easy_init();
914  if ( !_curl ) {
916  }
917  try
918  {
919  setupEasy();
920  }
921  catch (Exception & ex)
922  {
923  disconnectFrom();
924  ZYPP_RETHROW(ex);
925  }
926 
927  // FIXME: need a derived class to propelly compare url's
929  setMediaSource(media);
930 }
931 
932 bool
934 {
935  return MediaHandler::checkAttachPoint( apoint, true, true);
936 }
937 
939 
941 {
942  if ( _customHeaders )
943  {
944  curl_slist_free_all(_customHeaders);
945  _customHeaders = 0L;
946  }
947 
948  if ( _curl )
949  {
950  curl_easy_cleanup( _curl );
951  _curl = NULL;
952  }
953 }
954 
956 
957 void MediaCurl::releaseFrom( const std::string & ejectDev )
958 {
959  disconnect();
960 }
961 
962 Url MediaCurl::getFileUrl( const Pathname & filename_r ) const
963 {
964  // Simply extend the URLs pathname. An 'absolute' URL path
965  // is achieved by encoding the leading '/' in an URL path:
966  // URL: ftp://user@server -> ~user
967  // URL: ftp://user@server/ -> ~user
968  // URL: ftp://user@server// -> ~user
969  // URL: ftp://user@server/%2F -> /
970  // ^- this '/' is just a separator
971  Url newurl( _url );
972  newurl.setPathName( ( Pathname("./"+_url.getPathName()) / filename_r ).asString().substr(1) );
973  return newurl;
974 }
975 
977 
978 void MediaCurl::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
979 {
980  // Use absolute file name to prevent access of files outside of the
981  // hierarchy below the attach point.
982  getFileCopy(filename, localPath(filename).absolutename(), expectedFileSize_r);
983 }
984 
986 
987 void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target, const ByteCount &expectedFileSize_r ) const
988 {
990 
991  Url fileurl(getFileUrl(filename));
992 
993  bool retry = false;
994 
995  do
996  {
997  try
998  {
999  doGetFileCopy(filename, target, report, expectedFileSize_r);
1000  retry = false;
1001  }
1002  // retry with proper authentication data
1003  catch (MediaUnauthorizedException & ex_r)
1004  {
1005  if(authenticate(ex_r.hint(), !retry))
1006  retry = true;
1007  else
1008  {
1010  ZYPP_RETHROW(ex_r);
1011  }
1012  }
1013  // unexpected exception
1014  catch (MediaException & excpt_r)
1015  {
1017  if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) ||
1018  typeid(excpt_r) == typeid( media::MediaNotAFileException ) )
1019  {
1021  }
1022  report->finish(fileurl, reason, excpt_r.asUserHistory());
1023  ZYPP_RETHROW(excpt_r);
1024  }
1025  }
1026  while (retry);
1027 
1029 }
1030 
1032 
1033 bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
1034 {
1035  bool retry = false;
1036 
1037  do
1038  {
1039  try
1040  {
1041  return doGetDoesFileExist( filename );
1042  }
1043  // authentication problem, retry with proper authentication data
1044  catch (MediaUnauthorizedException & ex_r)
1045  {
1046  if(authenticate(ex_r.hint(), !retry))
1047  retry = true;
1048  else
1049  ZYPP_RETHROW(ex_r);
1050  }
1051  // unexpected exception
1052  catch (MediaException & excpt_r)
1053  {
1054  ZYPP_RETHROW(excpt_r);
1055  }
1056  }
1057  while (retry);
1058 
1059  return false;
1060 }
1061 
1063 
1065  CURLcode code,
1066  bool timeout_reached) const
1067 {
1068  if ( code != 0 )
1069  {
1070  Url url;
1071  if (filename.empty())
1072  url = _url;
1073  else
1074  url = getFileUrl(filename);
1075 
1076  std::string err;
1077  {
1078  switch ( code )
1079  {
1080  case CURLE_UNSUPPORTED_PROTOCOL:
1081  case CURLE_URL_MALFORMAT:
1082  case CURLE_URL_MALFORMAT_USER:
1083  err = " Bad URL";
1084  break;
1085  case CURLE_LOGIN_DENIED:
1086  ZYPP_THROW(
1087  MediaUnauthorizedException(url, "Login failed.", _curlError, ""));
1088  break;
1089  case CURLE_HTTP_RETURNED_ERROR:
1090  {
1091  long httpReturnCode = 0;
1092  CURLcode infoRet = curl_easy_getinfo( _curl,
1093  CURLINFO_RESPONSE_CODE,
1094  &httpReturnCode );
1095  if ( infoRet == CURLE_OK )
1096  {
1097  string msg = "HTTP response: " + str::numstring( httpReturnCode );
1098  switch ( httpReturnCode )
1099  {
1100  case 401:
1101  {
1102  string auth_hint = getAuthHint();
1103 
1104  DBG << msg << " Login failed (URL: " << url.asString() << ")" << std::endl;
1105  DBG << "MediaUnauthorizedException auth hint: '" << auth_hint << "'" << std::endl;
1106 
1108  url, "Login failed.", _curlError, auth_hint
1109  ));
1110  }
1111 
1112  case 502: // bad gateway (bnc #1070851)
1113  case 503: // service temporarily unavailable (bnc #462545)
1115  case 504: // gateway timeout
1117  case 403:
1118  {
1119  string msg403;
1120  if (url.asString().find("novell.com") != string::npos)
1121  msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired.");
1123  }
1124  case 404:
1125  case 410:
1127  }
1128 
1129  DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
1131  }
1132  else
1133  {
1134  string msg = "Unable to retrieve HTTP response:";
1135  DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
1137  }
1138  }
1139  break;
1140  case CURLE_FTP_COULDNT_RETR_FILE:
1141 #if CURLVERSION_AT_LEAST(7,16,0)
1142  case CURLE_REMOTE_FILE_NOT_FOUND:
1143 #endif
1144  case CURLE_FTP_ACCESS_DENIED:
1145  case CURLE_TFTP_NOTFOUND:
1146  err = "File not found";
1148  break;
1149  case CURLE_BAD_PASSWORD_ENTERED:
1150  case CURLE_FTP_USER_PASSWORD_INCORRECT:
1151  err = "Login failed";
1152  break;
1153  case CURLE_COULDNT_RESOLVE_PROXY:
1154  case CURLE_COULDNT_RESOLVE_HOST:
1155  case CURLE_COULDNT_CONNECT:
1156  case CURLE_FTP_CANT_GET_HOST:
1157  err = "Connection failed";
1158  break;
1159  case CURLE_WRITE_ERROR:
1160  err = "Write error";
1161  break;
1162  case CURLE_PARTIAL_FILE:
1163  case CURLE_OPERATION_TIMEDOUT:
1164  timeout_reached = true; // fall though to TimeoutException
1165  // fall though...
1166  case CURLE_ABORTED_BY_CALLBACK:
1167  if( timeout_reached )
1168  {
1169  err = "Timeout reached";
1171  }
1172  else
1173  {
1174  err = "User abort";
1175  }
1176  break;
1177  case CURLE_SSL_PEER_CERTIFICATE:
1178  default:
1179  err = "Curl error " + str::numstring( code );
1180  break;
1181  }
1182 
1183  // uhm, no 0 code but unknown curl exception
1185  }
1186  }
1187  else
1188  {
1189  // actually the code is 0, nothing happened
1190  }
1191 }
1192 
1194 
1195 bool MediaCurl::doGetDoesFileExist( const Pathname & filename ) const
1196 {
1197  DBG << filename.asString() << endl;
1198 
1199  if(!_url.isValid())
1201 
1202  if(_url.getHost().empty())
1204 
1205  Url url(getFileUrl(filename));
1206 
1207  DBG << "URL: " << url.asString() << endl;
1208  // Use URL without options and without username and passwd
1209  // (some proxies dislike them in the URL).
1210  // Curl seems to need the just scheme, hostname and a path;
1211  // the rest was already passed as curl options (in attachTo).
1212  Url curlUrl( clearQueryString(url) );
1213 
1214  //
1215  // See also Bug #154197 and ftp url definition in RFC 1738:
1216  // The url "ftp://user@host/foo/bar/file" contains a path,
1217  // that is relative to the user's home.
1218  // The url "ftp://user@host//foo/bar/file" (or also with
1219  // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
1220  // contains an absolute path.
1221  //
1222  string urlBuffer( curlUrl.asString());
1223  CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
1224  urlBuffer.c_str() );
1225  if ( ret != 0 ) {
1227  }
1228 
1229  // instead of returning no data with NOBODY, we return
1230  // little data, that works with broken servers, and
1231  // works for ftp as well, because retrieving only headers
1232  // ftp will return always OK code ?
1233  // See http://curl.haxx.se/docs/knownbugs.html #58
1234  if ( (_url.getScheme() == "http" || _url.getScheme() == "https") &&
1236  ret = curl_easy_setopt( _curl, CURLOPT_NOBODY, 1L );
1237  else
1238  ret = curl_easy_setopt( _curl, CURLOPT_RANGE, "0-1" );
1239 
1240  if ( ret != 0 ) {
1241  curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
1242  curl_easy_setopt( _curl, CURLOPT_RANGE, NULL );
1243  /* yes, this is why we never got to get NOBODY working before,
1244  because setting it changes this option too, and we also
1245  need to reset it
1246  See: http://curl.haxx.se/mail/archive-2005-07/0073.html
1247  */
1248  curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
1250  }
1251 
1252  AutoFILE file { ::fopen( "/dev/null", "w" ) };
1253  if ( !file ) {
1254  ERR << "fopen failed for /dev/null" << endl;
1255  curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
1256  curl_easy_setopt( _curl, CURLOPT_RANGE, NULL );
1257  /* yes, this is why we never got to get NOBODY working before,
1258  because setting it changes this option too, and we also
1259  need to reset it
1260  See: http://curl.haxx.se/mail/archive-2005-07/0073.html
1261  */
1262  curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
1263  if ( ret != 0 ) {
1265  }
1266  ZYPP_THROW(MediaWriteException("/dev/null"));
1267  }
1268 
1269  ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, (*file) );
1270  if ( ret != 0 ) {
1271  std::string err( _curlError);
1272  curl_easy_setopt( _curl, CURLOPT_RANGE, NULL );
1273  curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
1274  /* yes, this is why we never got to get NOBODY working before,
1275  because setting it changes this option too, and we also
1276  need to reset it
1277  See: http://curl.haxx.se/mail/archive-2005-07/0073.html
1278  */
1279  curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
1280  if ( ret != 0 ) {
1282  }
1284  }
1285 
1286  CURLcode ok = curl_easy_perform( _curl );
1287  MIL << "perform code: " << ok << " [ " << curl_easy_strerror(ok) << " ]" << endl;
1288 
1289  // reset curl settings
1290  if ( _url.getScheme() == "http" || _url.getScheme() == "https" )
1291  {
1292  curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
1293  if ( ret != 0 ) {
1295  }
1296 
1297  /* yes, this is why we never got to get NOBODY working before,
1298  because setting it changes this option too, and we also
1299  need to reset it
1300  See: http://curl.haxx.se/mail/archive-2005-07/0073.html
1301  */
1302  curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L);
1303  if ( ret != 0 ) {
1305  }
1306 
1307  }
1308  else
1309  {
1310  // for FTP we set different options
1311  curl_easy_setopt( _curl, CURLOPT_RANGE, NULL);
1312  if ( ret != 0 ) {
1314  }
1315  }
1316 
1317  // as we are not having user interaction, the user can't cancel
1318  // the file existence checking, a callback or timeout return code
1319  // will be always a timeout.
1320  try {
1321  evaluateCurlCode( filename, ok, true /* timeout */);
1322  }
1323  catch ( const MediaFileNotFoundException &e ) {
1324  // if the file did not exist then we can return false
1325  return false;
1326  }
1327  catch ( const MediaException &e ) {
1328  // some error, we are not sure about file existence, rethrw
1329  ZYPP_RETHROW(e);
1330  }
1331  // exists
1332  return ( ok == CURLE_OK );
1333 }
1334 
1336 
1337 
1338 #if DETECT_DIR_INDEX
1339 bool MediaCurl::detectDirIndex() const
1340 {
1341  if(_url.getScheme() != "http" && _url.getScheme() != "https")
1342  return false;
1343  //
1344  // try to check the effective url and set the not_a_file flag
1345  // if the url path ends with a "/", what usually means, that
1346  // we've received a directory index (index.html content).
1347  //
1348  // Note: This may be dangerous and break file retrieving in
1349  // case of some server redirections ... ?
1350  //
1351  bool not_a_file = false;
1352  char *ptr = NULL;
1353  CURLcode ret = curl_easy_getinfo( _curl,
1354  CURLINFO_EFFECTIVE_URL,
1355  &ptr);
1356  if ( ret == CURLE_OK && ptr != NULL)
1357  {
1358  try
1359  {
1360  Url eurl( ptr);
1361  std::string path( eurl.getPathName());
1362  if( !path.empty() && path != "/" && *path.rbegin() == '/')
1363  {
1364  DBG << "Effective url ("
1365  << eurl
1366  << ") seems to provide the index of a directory"
1367  << endl;
1368  not_a_file = true;
1369  }
1370  }
1371  catch( ... )
1372  {}
1373  }
1374  return not_a_file;
1375 }
1376 #endif
1377 
1379 
1380 void MediaCurl::doGetFileCopy(const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
1381 {
1382  Pathname dest = target.absolutename();
1383  if( assert_dir( dest.dirname() ) )
1384  {
1385  DBG << "assert_dir " << dest.dirname() << " failed" << endl;
1386  ZYPP_THROW( MediaSystemException(getFileUrl(filename), "System error on " + dest.dirname().asString()) );
1387  }
1388 
1389  ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) };
1390  AutoFILE file;
1391  {
1392  AutoFREE<char> buf { ::strdup( (*destNew).c_str() ) };
1393  if( ! buf )
1394  {
1395  ERR << "out of memory for temp file name" << endl;
1396  ZYPP_THROW(MediaSystemException(getFileUrl(filename), "out of memory for temp file name"));
1397  }
1398 
1399  AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
1400  if( tmp_fd == -1 )
1401  {
1402  ERR << "mkstemp failed for file '" << destNew << "'" << endl;
1403  ZYPP_THROW(MediaWriteException(destNew));
1404  }
1405  destNew = ManagedFile( (*buf), filesystem::unlink );
1406 
1407  file = ::fdopen( tmp_fd, "we" );
1408  if ( ! file )
1409  {
1410  ERR << "fopen failed for file '" << destNew << "'" << endl;
1411  ZYPP_THROW(MediaWriteException(destNew));
1412  }
1413  tmp_fd.resetDispose(); // don't close it here! ::fdopen moved ownership to file
1414  }
1415 
1416  DBG << "dest: " << dest << endl;
1417  DBG << "temp: " << destNew << endl;
1418 
1419  // set IFMODSINCE time condition (no download if not modified)
1420  if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) )
1421  {
1422  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
1423  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime());
1424  }
1425  else
1426  {
1427  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1428  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
1429  }
1430  try
1431  {
1432  doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
1433  }
1434  catch (Exception &e)
1435  {
1436  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1437  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
1438  ZYPP_RETHROW(e);
1439  }
1440 
1441  long httpReturnCode = 0;
1442  CURLcode infoRet = curl_easy_getinfo(_curl,
1443  CURLINFO_RESPONSE_CODE,
1444  &httpReturnCode);
1445  bool modified = true;
1446  if (infoRet == CURLE_OK)
1447  {
1448  DBG << "HTTP response: " + str::numstring(httpReturnCode);
1449  if ( httpReturnCode == 304
1450  || ( httpReturnCode == 213 && (_url.getScheme() == "ftp" || _url.getScheme() == "tftp") ) ) // not modified
1451  {
1452  DBG << " Not modified.";
1453  modified = false;
1454  }
1455  DBG << endl;
1456  }
1457  else
1458  {
1459  WAR << "Could not get the reponse code." << endl;
1460  }
1461 
1462  if (modified || infoRet != CURLE_OK)
1463  {
1464  // apply umask
1465  if ( ::fchmod( ::fileno(file), filesystem::applyUmaskTo( 0644 ) ) )
1466  {
1467  ERR << "Failed to chmod file " << destNew << endl;
1468  }
1469 
1470  file.resetDispose(); // we're going to close it manually here
1471  if ( ::fclose( file ) )
1472  {
1473  ERR << "Fclose failed for file '" << destNew << "'" << endl;
1474  ZYPP_THROW(MediaWriteException(destNew));
1475  }
1476 
1477  // move the temp file into dest
1478  if ( rename( destNew, dest ) != 0 ) {
1479  ERR << "Rename failed" << endl;
1481  }
1482  destNew.resetDispose(); // no more need to unlink it
1483  }
1484 
1485  DBG << "done: " << PathInfo(dest) << endl;
1486 }
1487 
1489 
1490 void MediaCurl::doGetFileCopyFile(const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
1491 {
1492  DBG << filename.asString() << endl;
1493 
1494  if(!_url.isValid())
1496 
1497  if(_url.getHost().empty())
1499 
1500  Url url(getFileUrl(filename));
1501 
1502  DBG << "URL: " << url.asString() << endl;
1503  // Use URL without options and without username and passwd
1504  // (some proxies dislike them in the URL).
1505  // Curl seems to need the just scheme, hostname and a path;
1506  // the rest was already passed as curl options (in attachTo).
1507  Url curlUrl( clearQueryString(url) );
1508 
1509  //
1510  // See also Bug #154197 and ftp url definition in RFC 1738:
1511  // The url "ftp://user@host/foo/bar/file" contains a path,
1512  // that is relative to the user's home.
1513  // The url "ftp://user@host//foo/bar/file" (or also with
1514  // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
1515  // contains an absolute path.
1516  //
1517  string urlBuffer( curlUrl.asString());
1518  CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
1519  urlBuffer.c_str() );
1520  if ( ret != 0 ) {
1522  }
1523 
1524  ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, file );
1525  if ( ret != 0 ) {
1527  }
1528 
1529  // Set callback and perform.
1530  ProgressData progressData(_curl, _settings.timeout(), url, expectedFileSize_r, &report);
1531  if (!(options & OPTION_NO_REPORT_START))
1532  report->start(url, dest);
1533  if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) {
1534  WAR << "Can't set CURLOPT_PROGRESSDATA: " << _curlError << endl;;
1535  }
1536 
1537  ret = curl_easy_perform( _curl );
1538 #if CURLVERSION_AT_LEAST(7,19,4)
1539  // bnc#692260: If the client sends a request with an If-Modified-Since header
1540  // with a future date for the server, the server may respond 200 sending a
1541  // zero size file.
1542  // curl-7.19.4 introduces CURLINFO_CONDITION_UNMET to check this condition.
1543  if ( ftell(file) == 0 && ret == 0 )
1544  {
1545  long httpReturnCode = 33;
1546  if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 )
1547  {
1548  long conditionUnmet = 33;
1549  if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet )
1550  {
1551  WAR << "TIMECONDITION unmet - retry without." << endl;
1552  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1553  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
1554  ret = curl_easy_perform( _curl );
1555  }
1556  }
1557  }
1558 #endif
1559 
1560  if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, NULL ) != 0 ) {
1561  WAR << "Can't unset CURLOPT_PROGRESSDATA: " << _curlError << endl;;
1562  }
1563 
1564  if ( ret != 0 )
1565  {
1566  ERR << "curl error: " << ret << ": " << _curlError
1567  << ", temp file size " << ftell(file)
1568  << " bytes." << endl;
1569 
1570  // the timeout is determined by the progress data object
1571  // which holds whether the timeout was reached or not,
1572  // otherwise it would be a user cancel
1573  try {
1574 
1575  if ( progressData.fileSizeExceeded )
1576  ZYPP_THROW(MediaFileSizeExceededException(url, progressData._expectedFileSize));
1577 
1578  evaluateCurlCode( filename, ret, progressData.reached );
1579  }
1580  catch ( const MediaException &e ) {
1581  // some error, we are not sure about file existence, rethrw
1582  ZYPP_RETHROW(e);
1583  }
1584  }
1585 
1586 #if DETECT_DIR_INDEX
1587  if (!ret && detectDirIndex())
1588  {
1590  }
1591 #endif // DETECT_DIR_INDEX
1592 }
1593 
1595 
1596 void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const
1597 {
1598  filesystem::DirContent content;
1599  getDirInfo( content, dirname, /*dots*/false );
1600 
1601  for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1602  Pathname filename = dirname + it->name;
1603  int res = 0;
1604 
1605  switch ( it->type ) {
1606  case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
1607  case filesystem::FT_FILE:
1608  getFile( filename, 0 );
1609  break;
1610  case filesystem::FT_DIR: // newer directory.yast contain at least directory info
1611  if ( recurse_r ) {
1612  getDir( filename, recurse_r );
1613  } else {
1614  res = assert_dir( localPath( filename ) );
1615  if ( res ) {
1616  WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl;
1617  }
1618  }
1619  break;
1620  default:
1621  // don't provide devices, sockets, etc.
1622  break;
1623  }
1624  }
1625 }
1626 
1628 
1629 void MediaCurl::getDirInfo( std::list<std::string> & retlist,
1630  const Pathname & dirname, bool dots ) const
1631 {
1632  getDirectoryYast( retlist, dirname, dots );
1633 }
1634 
1636 
1638  const Pathname & dirname, bool dots ) const
1639 {
1640  getDirectoryYast( retlist, dirname, dots );
1641 }
1642 
1644 //
1645 int MediaCurl::aliveCallback( void *clientp, double /*dltotal*/, double dlnow, double /*ultotal*/, double /*ulnow*/ )
1646 {
1647  ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
1648  if( pdata )
1649  {
1650  // Do not propagate dltotal in alive callbacks. MultiCurl uses this to
1651  // prevent a percentage raise while downloading a metalink file. Download
1652  // activity however is indicated by propagating the download rate (via dlnow).
1653  pdata->updateStats( 0.0, dlnow );
1654  return pdata->reportProgress();
1655  }
1656  return 0;
1657 }
1658 
1659 int MediaCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
1660 {
1661  ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
1662  if( pdata )
1663  {
1664  // work around curl bug that gives us old data
1665  long httpReturnCode = 0;
1666  if ( curl_easy_getinfo( pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0 )
1667  return aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow );
1668 
1669  pdata->updateStats( dltotal, dlnow );
1670  return pdata->reportProgress();
1671  }
1672  return 0;
1673 }
1674 
1676 {
1677  ProgressData *pdata = reinterpret_cast<ProgressData *>(clientp);
1678  return pdata ? pdata->curl : 0;
1679 }
1680 
1682 
1684 {
1685  long auth_info = CURLAUTH_NONE;
1686 
1687  CURLcode infoRet =
1688  curl_easy_getinfo(_curl, CURLINFO_HTTPAUTH_AVAIL, &auth_info);
1689 
1690  if(infoRet == CURLE_OK)
1691  {
1692  return CurlAuthData::auth_type_long2str(auth_info);
1693  }
1694 
1695  return "";
1696 }
1697 
1702 void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
1703 {
1704  ProgressData *data = reinterpret_cast<ProgressData *>(clientp);
1705  if ( data ) {
1706  data->_expectedFileSize = expectedFileSize;
1707  }
1708 }
1709 
1711 
1712 bool MediaCurl::authenticate(const string & availAuthTypes, bool firstTry) const
1713 {
1715  Target_Ptr target = zypp::getZYpp()->getTarget();
1716  CredentialManager cm(CredManagerOptions(target ? target->root() : ""));
1717  CurlAuthData_Ptr credentials;
1718 
1719  // get stored credentials
1720  AuthData_Ptr cmcred = cm.getCred(_url);
1721 
1722  if (cmcred && firstTry)
1723  {
1724  credentials.reset(new CurlAuthData(*cmcred));
1725  DBG << "got stored credentials:" << endl << *credentials << endl;
1726  }
1727  // if not found, ask user
1728  else
1729  {
1730 
1731  CurlAuthData_Ptr curlcred;
1732  curlcred.reset(new CurlAuthData());
1734 
1735  // preset the username if present in current url
1736  if (!_url.getUsername().empty() && firstTry)
1737  curlcred->setUsername(_url.getUsername());
1738  // if CM has found some credentials, preset the username from there
1739  else if (cmcred)
1740  curlcred->setUsername(cmcred->username());
1741 
1742  // indicate we have no good credentials from CM
1743  cmcred.reset();
1744 
1745  string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString();
1746 
1747  // set available authentication types from the exception
1748  // might be needed in prompt
1749  curlcred->setAuthType(availAuthTypes);
1750 
1751  // ask user
1752  if (auth_report->prompt(_url, prompt_msg, *curlcred))
1753  {
1754  DBG << "callback answer: retry" << endl
1755  << "CurlAuthData: " << *curlcred << endl;
1756 
1757  if (curlcred->valid())
1758  {
1759  credentials = curlcred;
1760  // if (credentials->username() != _url.getUsername())
1761  // _url.setUsername(credentials->username());
1769  }
1770  }
1771  else
1772  {
1773  DBG << "callback answer: cancel" << endl;
1774  }
1775  }
1776 
1777  // set username and password
1778  if (credentials)
1779  {
1780  // HACK, why is this const?
1781  const_cast<MediaCurl*>(this)->_settings.setUsername(credentials->username());
1782  const_cast<MediaCurl*>(this)->_settings.setPassword(credentials->password());
1783 
1784  // set username and password
1785  CURLcode ret = curl_easy_setopt(_curl, CURLOPT_USERPWD, _settings.userPassword().c_str());
1787 
1788  // set available authentication types from the exception
1789  if (credentials->authType() == CURLAUTH_NONE)
1790  credentials->setAuthType(availAuthTypes);
1791 
1792  // set auth type (seems this must be set _after_ setting the userpwd)
1793  if (credentials->authType() != CURLAUTH_NONE)
1794  {
1795  // FIXME: only overwrite if not empty?
1796  const_cast<MediaCurl*>(this)->_settings.setAuthType(credentials->authTypeAsString());
1797  ret = curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, credentials->authType());
1799  }
1800 
1801  if (!cmcred)
1802  {
1803  credentials->setUrl(_url);
1804  cm.addCred(*credentials);
1805  cm.save();
1806  }
1807 
1808  return true;
1809  }
1810 
1811  return false;
1812 }
1813 
1814 
1815  } // namespace media
1816 } // namespace zypp
1817 //
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:358
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:350
Interface to gettext.
#define _(MSG)
Definition: Gettext.h:29
#define DBG
Definition: Logger.h:63
#define MIL
Definition: Logger.h:64
#define ERR
Definition: Logger.h:66
#define WAR
Definition: Logger.h:65
double _dnlTotal
Bytes to download or 0 if unknown.
Definition: MediaCurl.cc:211
double uload
Definition: MediaCurl.cc:294
time_t _timeLast
Start last period(~1sec)
Definition: MediaCurl.cc:207
bool reached
Definition: MediaCurl.cc:201
bool fileSizeExceeded
Definition: MediaCurl.cc:202
ByteCount _expectedFileSize
Definition: MediaCurl.cc:204
#define CONNECT_TIMEOUT
Definition: MediaCurl.cc:42
double _drateTotal
Download rate so far.
Definition: MediaCurl.cc:217
double dload
Definition: MediaCurl.cc:292
#define SET_OPTION_OFFT(opt, val)
Definition: MediaCurl.cc:553
#define TRANSFER_TIMEOUT_MAX
Definition: MediaCurl.cc:43
double dload_period
Definition: MediaCurl.cc:284
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:203
long secs
Definition: MediaCurl.cc:286
int _dnlPercent
Percent completed or 0 if _dnlTotal is unknown.
Definition: MediaCurl.cc:215
CURL * curl
Definition: MediaCurl.cc:198
Url url
Definition: MediaCurl.cc:199
double _drateLast
Download rate in last period.
Definition: MediaCurl.cc:218
time_t ltime
Definition: MediaCurl.cc:290
time_t _timeNow
Now.
Definition: MediaCurl.cc:209
#define SET_OPTION(opt, val)
Definition: MediaCurl.cc:546
double drate_period
Definition: MediaCurl.cc:282
#define EXPLICITLY_NO_PROXY
Definition: MediaCurl.cc:45
double drate_avg
Definition: MediaCurl.cc:288
time_t _timeStart
Start total stats.
Definition: MediaCurl.cc:206
time_t _timeRcv
Start of no-data timeout.
Definition: MediaCurl.cc:208
double _dnlNow
Bytes downloaded now.
Definition: MediaCurl.cc:213
double _dnlLast
Bytes downloaded at period start.
Definition: MediaCurl.cc:212
time_t timeout
Definition: MediaCurl.cc:200
Convenience interface for handling authentication data of media user.
Edition * _value
Definition: SysContent.cc:311
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:162
Store and operate with byte count.
Definition: ByteCount.h:31
Base class for Exception.
Definition: Exception.h:144
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:91
const std::string & msg() const
Return the message string provided to the ctor.
Definition: Exception.h:193
Url manipulation class.
Definition: Url.h:88
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:491
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
Definition: Url.cc:566
void setFragment(const std::string &fragment, EEncoding eflag=zypp::url::E_DECODED)
Set the fragment string in the URL.
Definition: Url.cc:716
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:598
std::string getQueryParam(const std::string &param, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
Definition: Url.cc:654
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:758
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition: Url.cc:582
void delQueryParam(const std::string &param)
remove the specified query parameter.
Definition: Url.cc:839
bool isValid() const
Verifies the Url.
Definition: Url.cc:483
void setPassword(const std::string &pass, EEncoding eflag=zypp::url::E_DECODED)
Set the password in the URL authority.
Definition: Url.cc:733
void setPathParams(const std::string &params)
Set the path parameters.
Definition: Url.cc:785
void setUsername(const std::string &user, EEncoding eflag=zypp::url::E_DECODED)
Set the username in the URL authority.
Definition: Url.cc:724
std::string getPassword(EEncoding eflag=zypp::url::E_DECODED) const
Returns the password from the URL authority.
Definition: Url.cc:574
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:125
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
bool userMayRWX() const
Definition: PathInfo.h:353
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:166
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:123
bool absolute() const
Test for an absolute path.
Definition: Pathname.h:115
const std::string & asString() const
String representation.
Definition: Pathname.h:90
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Definition: Pathname.h:138
const char * c_str() const
String representation.
Definition: Pathname.h:109
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods.
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
Curl HTTP authentication data.
Definition: MediaUserAuth.h:74
static std::string auth_type_long2str(long auth_type)
Converts a long of ORed CURLAUTH_* identifiers into a string of comma separated list of authenticatio...
static long auth_type_str2long(std::string &auth_type_str)
Converts a string of comma separated list of authetication type names into a long of ORed CURLAUTH_* ...
Implementation class for FTP, HTTP and HTTPS MediaHandler.
Definition: MediaCurl.h:33
virtual void setupEasy()
initializes the curl easy handle with the data from the url
Definition: MediaCurl.cc:656
Url getFileUrl(const Pathname &filename) const
concatenate the attach url and the filename to a complete download url
Definition: MediaCurl.cc:962
static void setCookieFile(const Pathname &)
Definition: MediaCurl.cc:624
@ OPTION_NO_IFMODSINCE
to not add a IFMODSINCE header if target exists
Definition: MediaCurl.h:44
@ OPTION_NO_REPORT_START
do not send a start ProgressReport
Definition: MediaCurl.h:46
static void resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
MediaMultiCurl needs to reset the expected filesize in case a metalink file is downloaded otherwise t...
Definition: MediaCurl.cc:1702
std::string _currentCookieFile
Definition: MediaCurl.h:170
static int aliveCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
Definition: MediaCurl.cc:1645
static Pathname _cookieFile
Definition: MediaCurl.h:171
static int progressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
Callback reporting download progress.
Definition: MediaCurl.cc:1659
Url clearQueryString(const Url &url) const
Definition: MediaCurl.cc:593
std::string getAuthHint() const
Return a comma separated list of available authentication methods supported by server.
Definition: MediaCurl.cc:1683
char _curlError[CURL_ERROR_SIZE]
Definition: MediaCurl.h:175
void checkProtocol(const Url &url) const
check the url is supported by the curl library
Definition: MediaCurl.cc:631
virtual void disconnectFrom()
Definition: MediaCurl.cc:940
virtual void attachTo(bool next=false)
Call concrete handler to attach the media.
Definition: MediaCurl.cc:898
virtual void getFileCopy(const Pathname &srcFilename, const Pathname &targetFilename, const ByteCount &expectedFileSize_r) const override
Definition: MediaCurl.cc:987
bool detectDirIndex() const
void evaluateCurlCode(const zypp::Pathname &filename, CURLcode code, bool timeout) const
Evaluates a curl return code and throws the right MediaException filename Filename being downloaded c...
Definition: MediaCurl.cc:1064
TransferSettings _settings
Definition: MediaCurl.h:177
virtual bool getDoesFileExist(const Pathname &filename) const
Repeatedly calls doGetDoesFileExist() until it successfully returns, fails unexpectedly,...
Definition: MediaCurl.cc:1033
virtual void doGetFileCopy(const Pathname &srcFilename, const Pathname &targetFilename, callback::SendReport< DownloadProgressReport > &_report, const ByteCount &expectedFileSize_r, RequestOptions options=OPTION_NONE) const
Definition: MediaCurl.cc:1380
virtual void getDir(const Pathname &dirname, bool recurse_r) const
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition: MediaCurl.cc:1596
virtual void releaseFrom(const std::string &ejectDev)
Call concrete handler to release the media.
Definition: MediaCurl.cc:957
virtual void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Call concrete handler to provide a content list of directory on media via retlist.
Definition: MediaCurl.cc:1629
TransferSettings & settings()
Definition: MediaCurl.cc:618
bool authenticate(const std::string &availAuthTypes, bool firstTry) const
Definition: MediaCurl.cc:1712
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const override
Call concrete handler to provide file below attach point.
Definition: MediaCurl.cc:978
static CURL * progressCallback_getcurl(void *clientp)
Definition: MediaCurl.cc:1675
void doGetFileCopyFile(const Pathname &srcFilename, const Pathname &dest, FILE *file, callback::SendReport< DownloadProgressReport > &_report, const ByteCount &expectedFileSize_r, RequestOptions options=OPTION_NONE) const
Definition: MediaCurl.cc:1490
virtual bool doGetDoesFileExist(const Pathname &filename) const
Definition: MediaCurl.cc:1195
curl_slist * _customHeaders
Definition: MediaCurl.h:176
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
Definition: MediaCurl.cc:933
Just inherits Exception to separate media exceptions.
Abstract base class for 'physical' MediaHandler like MediaCD, etc.
Definition: MediaHandler.h:45
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Ask media manager, if the specified path is already used as attach point or if there are another atta...
Url url() const
Url used.
Definition: MediaHandler.h:507
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
void disconnect()
Use concrete handler to isconnect media.
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
Pathname localPath(const Pathname &pathname) const
Files provided will be available at 'localPath(filename)'.
const Url _url
Url to handle.
Definition: MediaHandler.h:110
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
Pathname attachPoint() const
Return the currently used attach point.
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:37
const std::string & hint() const
comma separated list of available authentication types
bool useProxyFor(const Url &url_r) const
Return true if enabled and url_r does not match noProxy.
Definition: ProxyInfo.cc:56
std::string proxy(const Url &url) const
Definition: ProxyInfo.cc:44
Holds transfer setting.
std::string proxy() const
proxy host
void setProxyEnabled(bool enabled)
whether the proxy is used or not
long maxDownloadSpeed() const
Maximum download speed (bytes per second)
void setProxy(const std::string &proxyhost)
proxy to use if it is enabled
void setCertificateAuthoritiesPath(const zypp::Pathname &path)
Sets the SSL certificate authorities path.
long connectTimeout() const
connection timeout
long timeout() const
transfer timeout
Headers::const_iterator headersEnd() const
end iterators to additional headers
void setUsername(const std::string &username)
sets the auth username
void addHeader(const std::string &header)
add a header, on the form "Foo: Bar"
void setPassword(const std::string &password)
sets the auth password
void setAuthType(const std::string &authtype)
set the allowed authentication types
std::string userPassword() const
returns the user and password as a user:pass string
long minDownloadSpeed() const
Minimum download speed (bytes per second) until the connection is dropped.
void setHeadRequestsAllowed(bool allowed)
set whether HEAD requests are allowed
void setVerifyHostEnabled(bool enabled)
Sets whether to verify host for ssl.
void setClientCertificatePath(const zypp::Pathname &path)
Sets the SSL client certificate file.
void setConnectTimeout(long t)
set the connect timeout
std::string userAgentString() const
user agent string
std::string proxyUserPassword() const
returns the proxy user and password as a user:pass string
bool verifyHostEnabled() const
Whether to verify host for ssl.
Pathname clientCertificatePath() const
SSL client certificate file.
Pathname certificateAuthoritiesPath() const
SSL certificate authorities path ( default: /etc/ssl/certs )
bool headRequestsAllowed() const
whether HEAD requests are allowed
std::string proxyUsername() const
proxy auth username
std::string authType() const
get the allowed authentication types
void setVerifyPeerEnabled(bool enabled)
Sets whether to verify host for ssl.
void setProxyPassword(const std::string &proxypass)
sets the proxy password
bool proxyEnabled() const
proxy is enabled
std::string username() const
auth username
void setAnonymousAuth()
sets anonymous authentication (ie: for ftp)
void setUserAgentString(const std::string &agent)
sets the user agent ie: "Mozilla v3"
void setProxyUsername(const std::string &proxyuser)
sets the proxy user
Pathname clientKeyPath() const
SSL client key file.
void setTimeout(long t)
set the transfer timeout
void setClientKeyPath(const zypp::Pathname &path)
Sets the SSL client key file.
Headers::const_iterator headersBegin() const
begin iterators to additional headers
bool verifyPeerEnabled() const
Whether to verify peer for ssl.
Definition: Arch.h:345
Definition: Fd.cc:29
int ZYPP_MEDIA_CURL_IPRESOLVE()
Definition: MediaCurl.cc:173
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition: PathInfo.h:809
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:653
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
Definition: PathInfo.cc:695
int rmdir(const Pathname &path)
Like 'rmdir'.
Definition: PathInfo.cc:367
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
static const char *const agentString()
initialized only once, this gets the agent string which also includes the curl version
Definition: MediaCurl.cc:526
shared_ptr< CurlAuthData > CurlAuthData_Ptr
static const char *const anonymousIdHeader()
initialized only once, this gets the anonymous id from the target, which we pass in the http header
Definition: MediaCurl.cc:490
static const char *const distributionFlavorHeader()
initialized only once, this gets the distribution flavor from the target, which we pass in the http h...
Definition: MediaCurl.cc:508
shared_ptr< AuthData > AuthData_Ptr
Definition: MediaUserAuth.h:69
void fillSettingsFromUrl(const Url &url, TransferSettings &s)
Fills the settings structure using options passed on the url for example ?timeout=x&proxy=foo.
Definition: MediaCurl.cc:325
void fillSettingsSystemProxy(const Url &url, TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Definition: MediaCurl.cc:462
SolvableIdType size_type
Definition: PoolMember.h:152
std::string numstring(char n, int w=0)
Definition: String.h:305
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
Definition: String.h:519
std::string escape(const C_Str &str_r, const char sep_r)
Escape desired character c using a backslash.
Definition: String.cc:369
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition: String.h:445
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:221
void callOnce(OnceFlag &flag, void(*func)())
Call once function.
Definition: Once.h:50
pthread_once_t OnceFlag
The OnceFlag variable type.
Definition: Once.h:32
@ E_ENCODED
Flag to request encoded string(s).
Definition: UrlUtils.h:53
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
AutoDispose<int> calling ::close
Definition: AutoDispose.h:204
AutoDispose<FILE*> calling ::fclose
Definition: AutoDispose.h:215
Structure holding values of curlrc options.
Definition: CurlConfig.h:17
std::string proxyuserpwd
Definition: CurlConfig.h:39
static int parseConfig(CurlConfig &config, const std::string &filename="")
Parse a curlrc file and store the result in the config structure.
Definition: CurlConfig.cc:24
Convenient building of std::string with boost::format.
Definition: String.h:249