libzypp  17.36.3
MediaCurl2.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <chrono>
15 #include <list>
16 
17 #include <zypp/base/Logger.h>
18 #include <zypp/ExternalProgram.h>
19 #include <zypp/base/String.h>
20 #include <zypp/base/Gettext.h>
21 #include <zypp-core/parser/Sysconfig>
22 #include <zypp/base/Gettext.h>
23 
24 #include <zypp/media/MediaCurl2.h>
25 
28 #include <zypp-curl/ProxyInfo>
29 #include <zypp-curl/auth/CurlAuthData>
30 #include <zypp-media/auth/CredentialManager>
31 #include <zypp-curl/CurlConfig>
33 #include <zypp/Target.h>
34 #include <zypp/ZYppFactory.h>
35 #include <zypp/ZConfig.h>
36 #include <zypp/zypp_detail/ZYppImpl.h> // for zypp_poll
37 
42 
43 #include <cstdlib>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/mount.h>
47 #include <dirent.h>
48 #include <unistd.h>
49 #include <glib.h>
50 
53 
54 #ifdef ENABLE_ZCHUNK_COMPRESSION
56 #endif
57 
58 
65 using std::endl;
66 
67 namespace internal {
68  using namespace zypp;
69 
70  struct ProgressTracker {
71 
72  using clock = std::chrono::steady_clock;
73 
74  std::optional<clock::time_point> _timeStart;
75  std::optional<clock::time_point> _timeLast;
76 
77  double _dnlTotal = 0.0;
78  double _dnlLast = 0.0;
79  double _dnlNow = 0.0;
80 
81  int _dnlPercent= 0;
82 
83  double _drateTotal= 0.0;
84  double _drateLast = 0.0;
85 
86  void updateStats( double dltotal = 0.0, double dlnow = 0.0 )
87  {
88  clock::time_point now = clock::now();
89 
90  if ( !_timeStart )
91  _timeStart = _timeLast = now;
92 
93  // If called without args (0.0), recompute based on the last values seen
94  if ( dltotal && dltotal != _dnlTotal )
95  _dnlTotal = dltotal;
96 
97  if ( dlnow && dlnow != _dnlNow ) {
98  _dnlNow = dlnow;
99  }
100 
101  // percentage:
102  if ( _dnlTotal )
103  _dnlPercent = int(_dnlNow * 100 / _dnlTotal);
104 
105  // download rates:
106  _drateTotal = _dnlNow / std::max( std::chrono::duration_cast<std::chrono::seconds>(now - *_timeStart).count(), int64_t(1) );
107 
108  if ( _timeLast < now )
109  {
110  _drateLast = (_dnlNow - _dnlLast) / int( std::chrono::duration_cast<std::chrono::seconds>(now - *_timeLast).count() );
111  // start new period
112  _timeLast = now;
113  _dnlLast = _dnlNow;
114  }
115  else if ( _timeStart == _timeLast )
116  _drateLast = _drateTotal;
117  }
118  };
119 }
120 
121 using namespace internal;
122 using namespace zypp::base;
123 
124 namespace zypp {
125 
126  namespace media {
127 
128  MediaCurl2::MediaCurl2( const Url & url_r,
129  const Pathname & attach_point_hint_r )
130  : MediaNetworkCommonHandler( url_r, attach_point_hint_r,
131  "/", // urlpath at attachpoint
132  true ) // does_download
133  , _evDispatcher( zyppng::ThreadData::current().ensureDispatcher() )
134  , _nwDispatcher( std::make_shared<zyppng::NetworkRequestDispatcher>() )
135  {
136 
137  MIL << "MediaCurl2::MediaCurl2(" << url_r << ", " << attach_point_hint_r << ")" << endl;
138 
139  if( !attachPoint().empty())
140  {
141  PathInfo ainfo(attachPoint());
142  Pathname apath(attachPoint() + "XXXXXX");
143  char *atemp = ::strdup( apath.asString().c_str());
144  char *atest = NULL;
145  if( !ainfo.isDir() || !ainfo.userMayRWX() ||
146  atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
147  {
148  WAR << "attach point " << ainfo.path()
149  << " is not useable for " << url_r.getScheme() << endl;
150  setAttachPoint("", true);
151  }
152  else if( atest != NULL)
153  ::rmdir(atest);
154 
155  if( atemp != NULL)
156  ::free(atemp);
157  }
158 
159  _nwDispatcher->setAgentString ( str::asString( agentString () ) );
160  _nwDispatcher->setHostSpecificHeader ("download.opensuse.org", "X-ZYpp-DistributionFlavor", str::asString(distributionFlavorHeader()) );
161  _nwDispatcher->setHostSpecificHeader ("download.opensuse.org", "X-ZYpp-AnonymousId", str::asString(anonymousIdHeader()) );
162  }
163 
165  {
167  }
168 
170 
171  void MediaCurl2::checkProtocol(const Url &url) const
172  {
173  if ( !zyppng::NetworkRequestDispatcher::supportsProtocol ( url ) )
174  {
175  std::string msg("Unsupported protocol '");
176  msg += url.getScheme();
177  msg += "'";
179  }
180  }
181 
183  {
184  // fill some settings from url query parameters
185  try
186  {
189  }
190  catch ( const MediaException &e )
191  {
192  disconnectFrom();
193  ZYPP_RETHROW(e);
194  }
195  // if the proxy was not set (or explicitly unset) by url, then look...
196  if ( _effectiveSettings.proxy().empty() )
197  {
198  // ...at the system proxy settings
200  }
201 
202  /* Fixes bsc#1174011 "auth=basic ignored in some cases"
203  * We should proactively add the password to the request if basic auth is configured
204  * and a password is available in the credentials but not in the URL.
205  *
206  * We will be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route
207  * and ask the server first about the auth method
208  */
209  if ( _effectiveSettings.authType() == "basic"
210  && _effectiveSettings.username().size()
211  && !_effectiveSettings.password().size() ) {
212 
213  CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot()));
214  const auto cred = cm.getCred( _url );
215  if ( cred && cred->valid() ) {
216  if ( !_effectiveSettings.username().size() )
217  _effectiveSettings.setUsername(cred->username());
218  _effectiveSettings.setPassword(cred->password());
219  }
220  }
221  }
222 
223  void MediaCurl2::attachTo (bool next)
224  {
225  if ( next )
227 
228  if ( !_url.isValid() )
230 
233  {
235  }
236 
237  disconnectFrom(); // clean state if needed
238 
239  // here : setup TransferSettings
240  setupEasy();
241 
242  // FIXME: need a derived class to propelly compare url's
244  setMediaSource(media);
245  }
246 
247  bool
249  {
250  return MediaHandler::checkAttachPoint( apoint, true, true);
251  }
252 
254  {
255  // clear effective settings
257  }
258 
260 
261  void MediaCurl2::releaseFrom( const std::string & ejectDev )
262  {
263  disconnect();
264  }
265 
267 
268  void MediaCurl2::getFile( const OnMediaLocation &file ) const
269  {
270  // Use absolute file name to prevent access of files outside of the
271  // hierarchy below the attach point.
272  getFileCopy( file, localPath(file.filename()).absolutename() );
273  }
274 
276 
277  void MediaCurl2::getFileCopy( const OnMediaLocation & srcFile , const Pathname & target ) const
278  {
279 
280  const auto &filename = srcFile.filename();
281 
282  // Optional files will send no report until data are actually received (we know it exists).
283  OptionalDownloadProgressReport reportfilter( srcFile.optional() );
285 
286  Url fileurl(getFileUrl(filename));
287  do
288  {
289  try
290  {
291  doGetFileCopy( srcFile, target, report );
292  break; // success!
293  }
294  // unexpected exception
295  catch (MediaException & excpt_r)
296  {
298  if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) ||
299  typeid(excpt_r) == typeid( media::MediaNotAFileException ) )
300  {
302  }
303  report->finish(fileurl, reason, excpt_r.asUserHistory());
304  ZYPP_RETHROW(excpt_r);
305  }
306  }
307  while ( true );
308  report->finish(fileurl, zypp::media::DownloadProgressReport::NO_ERROR, "");
309  }
310 
311  bool MediaCurl2::getDoesFileExist( const Pathname & filename ) const
312  {
313  DBG << filename.asString() << endl;
314 
315  if(!_url.isValid())
317 
318  if(_url.getHost().empty())
320 
321  Url url(getFileUrl(filename));
322 
323  DBG << "URL: " << url.asString() << endl;
324 
325  // Use URL without options and without username and passwd
326  // (some proxies dislike them in the URL).
327  // Curl seems to need the just scheme, hostname and a path;
328  // the rest was already passed as curl options (in attachTo).
329  Url curlUrl( clearQueryString(url) );
330 
331  auto req = std::make_shared<zyppng::NetworkRequest>( curlUrl, "/dev/null" );
332  req->setOptions ( zyppng::NetworkRequest::HeadRequest ); // just check for existance
333 
334  // as we are not having user interaction, the user can't cancel
335  // the file existence checking, a callback or timeout return code
336  // will be always a timeout.
337  try {
338  const_cast<MediaCurl2*>(this)->executeRequest ( req );
339  }
340  catch ( const MediaFileNotFoundException &e ) {
341  // if the file did not exist then we can return false
342  return false;
343  }
344  catch ( const MediaException &e ) {
345  // some error, we are not sure about file existence, rethrw
346  ZYPP_RETHROW(e);
347  }
348 
349  // exists
350  return ( !req->hasError() );
351  }
352 
354 
355  void MediaCurl2::doGetFileCopy( const OnMediaLocation &srcFile , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
356  {
357  Pathname dest = target.absolutename();
358  if( assert_dir( dest.dirname() ) ) {
359  DBG << "assert_dir " << dest.dirname() << " failed" << endl;
360  ZYPP_THROW( MediaSystemException(getFileUrl(srcFile.filename()), "System error on " + dest.dirname().asString()) );
361  }
362 
363  ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) }; {
364  AutoFREE<char> buf { ::strdup( (*destNew).c_str() ) };
365  if( ! buf ) {
366  ERR << "out of memory for temp file name" << endl;
367  ZYPP_THROW(MediaSystemException(getFileUrl(srcFile.filename()), "out of memory for temp file name"));
368  }
369 
370  AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
371  if( tmp_fd == -1 ) {
372  ERR << "mkstemp failed for file '" << destNew << "'" << endl;
374  }
375  destNew = ManagedFile( (*buf), filesystem::unlink );
376  }
377 
378  DBG << "dest: " << dest << endl;
379  DBG << "temp: " << destNew << endl;
380 #if 0
381  Not implemented here yet because NetworkRequest can not do IFMODSINCE yet
382  // set IFMODSINCE time condition (no download if not modified)
383  if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) )
384  {
385  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
386  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime());
387  }
388  else
389  {
390  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
391  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
392  }
393 #endif
394 
395  DBG << srcFile.filename().asString() << endl;
396 
397  if(!_url.isValid())
399 
400  if(_url.getHost().empty())
402 
403  Url url(getFileUrl(srcFile.filename()));
404 
405  DBG << "URL: " << url.asString() << endl;
406  // Use URL without options and without username and passwd
407  // (some proxies dislike them in the URL).
408  // Curl seems to need the just scheme, hostname and a path;
409  // the rest was already passed as curl options (in attachTo).
410  Url curlUrl( clearQueryString(url) );
411 
412  auto req = std::make_shared<zyppng::NetworkRequest>( curlUrl, destNew, zyppng::NetworkRequest::WriteShared /*do not truncate*/ );
413  req->setExpectedFileSize ( srcFile.downloadSize () );
414 
415  bool done = false;
416 #ifdef ENABLE_ZCHUNK_COMPRESSION
417  done = const_cast<MediaCurl2*>(this)->tryZchunk(req, srcFile, destNew, report);
418 #endif
419  if ( !done ) {
420  req->resetRequestRanges();
421  const_cast<MediaCurl2 *>(this)->executeRequest ( req, &report );
422  }
423 
424 #if 0
425  Also disabled IFMODSINCE code, see above while not yet implemented here
426  #if CURLVERSION_AT_LEAST(7,19,4)
427  // bnc#692260: If the client sends a request with an If-Modified-Since header
428  // with a future date for the server, the server may respond 200 sending a
429  // zero size file.
430  // curl-7.19.4 introduces CURLINFO_CONDITION_UNMET to check this condition.
431  if ( ftell(file) == 0 && ret == 0 )
432  {
433  long httpReturnCode = 33;
434  if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 )
435  {
436  long conditionUnmet = 33;
437  if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet )
438  {
439  WAR << "TIMECONDITION unmet - retry without." << endl;
440  curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
441  curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
442  ret = executeCurl();
443  }
444  }
445  }
446 #endif
447 #endif
448 
449 
450  // apply umask
451  if ( ::chmod( destNew->c_str(), filesystem::applyUmaskTo( 0644 ) ) )
452  {
453  ERR << "Failed to chmod file " << destNew << endl;
454  }
455 
456  // move the temp file into dest
457  if ( rename( destNew, dest ) != 0 ) {
458  ERR << "Rename failed" << endl;
460  }
461  destNew.resetDispose(); // no more need to unlink it
462 
463  DBG << "done: " << PathInfo(dest) << endl;
464  }
465 
466 
467  bool MediaCurl2::tryZchunk( zyppng::NetworkRequestRef req, const OnMediaLocation &srcFile, const Pathname &target, callback::SendReport<DownloadProgressReport> &report )
468  {
469 #ifdef ENABLE_ZCHUNK_COMPRESSION
470 
471  // HERE add zchunk logic if required
472  if ( !srcFile.deltafile().empty()
474  && srcFile.headerSize () > 0 ) {
475 
476  // first fetch the zck header
477  std::optional<zypp::Digest> digest;
478  UByteArray sum;
479 
480  const auto &headerSum = srcFile.headerChecksum();
481  if ( !headerSum.empty () ) {
482  digest = zypp::Digest();
483  if ( !digest->create( headerSum.type() ) ) {
484  ERR << "Unknown header checksum type " << headerSum.type() << std::endl;
485  return false;
486  }
487  sum = zypp::Digest::hexStringToUByteArray( headerSum.checksum() );
488  }
489 
490  req->addRequestRange( 0, srcFile.headerSize(), std::move(digest), sum );
491  executeRequest ( req, nullptr );
492 
493  req->resetRequestRanges();
494 
495  auto res = zyppng::ZckHelper::prepareZck( srcFile.deltafile(), target, srcFile.downloadSize() );
496  switch(res._code) {
498  ERR << "Failed to setup zchunk because of: " << res._message << std::endl;
499  return false;
500  }
502  return true; // already done
504  ZYPP_THROW( MediaFileSizeExceededException( req->url(), srcFile.downloadSize(), res._message ));
506  break;
507  }
508 
509  for ( const auto &block : res._blocks ) {
510  if ( block._checksum.size() && block._chksumtype.size() ) {
511  std::optional<zypp::Digest> dig = zypp::Digest();
512  if ( !dig->create( block._chksumtype ) ) {
513  WAR_MEDIA << "Trying to create Digest with chksum type " << block._chksumtype << " failed " << std::endl;
514  return false;
515  }
516 
518  DBG_MEDIA << "Starting block " << block._start << " with checksum " << zypp::Digest::digestVectorToString( block._checksum ) << "." << std::endl;
519  req->addRequestRange( block._start, block._len, std::move(dig), block._checksum, {}, block._relevantDigestLen, block._chksumPad );
520  }
521  };
522 
523  executeRequest ( req, &report );
524 
525  //we might have the file ready
526  std::string err;
527  if ( !zyppng::ZckHelper::validateZckFile( target, err) ) {
528  ERR << "ZCK failed with error: " << err << std::endl;
529  return false;
530  }
531  return true;
532  }
533 #endif
534  return false;
535  }
536 
537 
538 
540 
541  void MediaCurl2::getDir( const Pathname & dirname, bool recurse_r ) const
542  {
543  filesystem::DirContent content;
544  getDirInfo( content, dirname, /*dots*/false );
545 
546  for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
547  Pathname filename = dirname + it->name;
548  int res = 0;
549 
550  switch ( it->type ) {
551  case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
552  case filesystem::FT_FILE:
553  getFile( OnMediaLocation( filename ) );
554  break;
555  case filesystem::FT_DIR: // newer directory.yast contain at least directory info
556  if ( recurse_r ) {
557  getDir( filename, recurse_r );
558  } else {
559  res = assert_dir( localPath( filename ) );
560  if ( res ) {
561  WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl;
562  }
563  }
564  break;
565  default:
566  // don't provide devices, sockets, etc.
567  break;
568  }
569  }
570  }
571 
573 
574  void MediaCurl2::getDirInfo( std::list<std::string> & retlist,
575  const Pathname & dirname, bool dots ) const
576  {
577  getDirectoryYast( retlist, dirname, dots );
578  }
579 
581 
583  const Pathname & dirname, bool dots ) const
584  {
585  getDirectoryYast( retlist, dirname, dots );
586  }
587 
588  void MediaCurl2::executeRequest( zyppng::NetworkRequestRef req , callback::SendReport<DownloadProgressReport> *report )
589  {
590  auto loop = zyppng::EventLoop::create();
591 
592  _nwDispatcher->run();
593 
594  bool firstAuth = true;
595  bool retry = true;
596  int maxTries = _effectiveSettings.maxSilentTries();
597 
598  while ( retry ) {
599  std::optional<internal::ProgressTracker> progTracker;
600 
601  std::vector<zyppng::connection> signalConnections {
602  req->sigStarted().connect( [&]( zyppng::NetworkRequest &req ){
603  if ( !report) return;
604  (*report)->start( req.url(), req.targetFilePath() );
605  }),
606  req->sigProgress().connect( [&]( zyppng::NetworkRequest &req, off_t dlTotal, off_t dlNow, off_t, off_t ){
607  if ( !report || !progTracker )
608  return;
609 
610  progTracker->updateStats( dlTotal, dlNow );
611  if ( !(*report)->progress( progTracker->_dnlPercent, req.url(), progTracker-> _drateTotal, progTracker->_drateLast ) )
612  _nwDispatcher->cancel ( req );
613 
614  }),
615  req->sigFinished().connect( [&]( zyppng::NetworkRequest &req, const zyppng::NetworkRequestError &err ) {
616  loop->quit();
617  })
618  };
619 
620  // clean up slots for every loop
621  zypp_defer {
622  std::for_each( signalConnections.begin(), signalConnections.end(), []( auto &conn ) { conn.disconnect(); });
623  signalConnections.clear();
624  };
625 
626  if ( report ) {
627  progTracker = internal::ProgressTracker();
628  }
629 
630  maxTries--;
631  retry = false; // normally we don't retry
632  req->transferSettings() = _effectiveSettings; // use settings from MediaCurl
633  _nwDispatcher->enqueue ( req );
634  loop->run();
635 
636  // once the request is done there should be nothing there anymore
637  if ( _nwDispatcher->count () != 0 ) {
638  ZYPP_THROW( zypp::Exception("Unexpected request count after finishing MediaCurl2 request!") );
639  }
640 
641  if ( req->hasError() ) {
643  std::exception_ptr excp;
644  const auto &error = req->error();
645  switch ( error.type() ) {
655  excp = ZYPP_EXCPT_PTR( zypp::media::MediaCurlException( req->url(), error.toString(), error.nativeErrorString() ) );
656  break;
657  }
659  excp = ZYPP_EXCPT_PTR( zypp::media::MediaRequestCancelledException( error.toString() ) );
660  break;
661  }
663  excp = ZYPP_EXCPT_PTR( zypp::media::MediaFileSizeExceededException( req->url(), req->expectedFileSize() ) );
664  break;
665  }
667  excp = ZYPP_EXCPT_PTR( zypp::media::MediaTemporaryProblemException( req->url(), error.toString() ) );
668  break;
669  }
671  excp = ZYPP_EXCPT_PTR( zypp::media::MediaTimeoutException( req->url(), error.toString() ) );
672  break;
673  }
675  excp = ZYPP_EXCPT_PTR( zypp::media::MediaForbiddenException( req->url(), error.toString() ) );
676  break;
677  }
680 
681  //@BUG using getPathName() can result in wrong error messages
683  break;
684  }
687 
688  //in case we got a auth hint from the server the error object will contain it
689  std::string authHint = error.extraInfoValue("authHint", std::string());
690  if ( authenticate( authHint, firstAuth ) ) {
691  firstAuth = false;
692  retry = true;
693  continue;
694  }
695 
697  excp = ZYPP_EXCPT_PTR( zypp::media::MediaUnauthorizedException( req->url(), error.toString(), error.nativeErrorString(), "" ) );
698  break;
699  }
701  // should never happen
702  DBG << "BUG: Download error flag is set , but Error code is NoError" << std::endl;
703  break;
706  excp = ZYPP_EXCPT_PTR( zypp::media::MediaCurlException( req->url(), error.toString(), error.nativeErrorString() ) );
707  break;
708  }
709  }
710 
711  if ( excp ) {
712  if ( maxTries > 0 ) {
713  retry = true;
714  continue;
715  }
716 
717  if ( report ) (*report)->finish( req->url(), errCode, error.toString() );
718  std::rethrow_exception( excp );
719  }
720  }
721 
722  }
723 
724  if ( report ) (*report)->finish( req->url(), zypp::media::DownloadProgressReport::NO_ERROR, "" );
725  }
726 
728 
729  bool MediaCurl2::authenticate(const std::string & availAuthTypes, bool firstTry)
730  {
732  CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot()));
733  CurlAuthData_Ptr credentials;
734 
735  // get stored credentials
736  AuthData_Ptr cmcred = cm.getCred(_url);
737 
738  if (cmcred && firstTry)
739  {
740  credentials.reset(new CurlAuthData(*cmcred));
741  DBG << "got stored credentials:" << endl << *credentials << endl;
742  }
743  // if not found, ask user
744  else
745  {
746 
747  CurlAuthData_Ptr curlcred;
748  curlcred.reset(new CurlAuthData());
750 
751  // preset the username if present in current url
752  if (!_url.getUsername().empty() && firstTry)
753  curlcred->setUsername(_url.getUsername());
754  // if CM has found some credentials, preset the username from there
755  else if (cmcred)
756  curlcred->setUsername(cmcred->username());
757 
758  // indicate we have no good credentials from CM
759  cmcred.reset();
760 
761  std::string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString();
762 
763  // set available authentication types from the exception
764  // might be needed in prompt
765  curlcred->setAuthType(availAuthTypes);
766 
767  // ask user
768  if (auth_report->prompt(_url, prompt_msg, *curlcred))
769  {
770  DBG << "callback answer: retry" << endl
771  << "CurlAuthData: " << *curlcred << endl;
772 
773  if (curlcred->valid())
774  {
775  credentials = curlcred;
776  // if (credentials->username() != _url.getUsername())
777  // _url.setUsername(credentials->username());
785  }
786  }
787  else
788  {
789  DBG << "callback answer: cancel" << endl;
790  }
791  }
792 
793  // set username and password
794  if (credentials)
795  {
796  _effectiveSettings.setUsername(credentials->username());
797  _effectiveSettings.setPassword(credentials->password());
798 
799  // set available authentication types from the exception
800  if (credentials->authType() == CURLAUTH_NONE)
801  credentials->setAuthType(availAuthTypes);
802 
803  // set auth type (seems this must be set _after_ setting the userpwd)
804  if (credentials->authType() != CURLAUTH_NONE) {
805  _effectiveSettings.setAuthType(credentials->authTypeAsString());
806  }
807 
808  if (!cmcred)
809  {
810  credentials->setUrl(_url);
811  cm.addCred(*credentials);
812  cm.save();
813  }
814 
815  return true;
816  }
817 
818  return false;
819  }
820 
821  } // namespace media
822 } // namespace zypp
823 //
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:551
Url getFileUrl(const Pathname &filename) const
concatenate the attach url and the filename to a complete download url
Interface to gettext.
#define MIL
Definition: Logger.h:100
#define DBG_MEDIA
Definition: mediadebug_p.h:28
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:324
const ByteCount & headerSize() const
The size of the header prepending the resource (e.g.
#define _(MSG)
Definition: Gettext.h:39
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:251
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:424
Implementation class for FTP, HTTP and HTTPS MediaHandler.
Definition: MediaCurl2.h:38
Describes a resource file located on a medium.
bool getDoesFileExist(const Pathname &filename) const override
Repeatedly calls doGetDoesFileExist() until it successfully returns, fails unexpectedly, or user cancels the operation.
Definition: MediaCurl2.cc:311
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:935
void setPassword(const std::string &val_r)
sets the auth password
void setupEasy()
initializes the curl easy handle with the data from the url
Definition: MediaCurl2.cc:182
Compute Message Digests (MD5, SHA1 etc)
Definition: Digest.h:37
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
void getFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename) const override
Definition: MediaCurl2.cc:277
void executeRequest(zyppng::NetworkRequestRef req, callback::SendReport< DownloadProgressReport > *report=nullptr)
Definition: MediaCurl2.cc:588
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods. ...
const std::string & authType() const
get the allowed authentication types
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:175
int chmod(const Pathname &path, mode_t mode)
Like &#39;chmod&#39;.
Definition: PathInfo.cc:1097
Url clearQueryString(const Url &url)
Definition: curlhelper.cc:380
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
std::optional< clock::time_point > _timeLast
Start last period(~1sec)
Definition: MediaCurl2.cc:75
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...
void setUsername(const std::string &val_r)
sets the auth username
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
Definition: String.h:139
Definition: Arch.h:363
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
bool tryZchunk(zyppng::NetworkRequestRef req, const OnMediaLocation &srcFile, const Pathname &target, callback::SendReport< DownloadProgressReport > &report)
Definition: MediaCurl2.cc:467
Convenient building of std::string with boost::format.
Definition: String.h:252
void disconnectFrom() override
Definition: MediaCurl2.cc:253
AutoDispose<int> calling ::close
Definition: AutoDispose.h:309
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition: Exception.h:428
const std::string & password() const
auth password
#define zypp_defer
Definition: AutoDispose.h:293
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:526
#define ERR
Definition: Logger.h:102
const std::string & username() const
auth username
static bool isZchunkFile(const zypp::Pathname &file)
Definition: zckhelper.cc:21
Pathname localPath(const Pathname &pathname) const
Files provided will be available at &#39;localPath(filename)&#39;.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
static std::string digestVectorToString(const UByteArray &vec)
get hex string representation of the digest vector given as parameter
Definition: Digest.cc:243
long maxSilentTries() const
Maximum silent retries.
bool authenticate(const std::string &availAuthTypes, bool firstTry)
Definition: MediaCurl2.cc:729
bool empty() const
Test for an empty path.
Definition: Pathname.h:116
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:444
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:515
Bottleneck filtering all DownloadProgressReport issued from Media[Muli]Curl.
void setAuthType(const std::string &val_r)
set the allowed authentication types
const Url _url
Url to handle.
Definition: MediaHandler.h:113
std::optional< clock::time_point > _timeStart
Start total stats.
Definition: MediaCurl2.cc:74
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
const std::string & asString() const
String representation.
Definition: Pathname.h:93
TransferSettings _effectiveSettings
Definition: MediaCurl2.h:130
Just inherits Exception to separate media exceptions.
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:127
const ByteCount & downloadSize() const
The size of the resource on the server.
void disconnect()
Use concrete handler to isconnect media.
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:126
#define WAR
Definition: Logger.h:101
void updateStats(double dltotal=0.0, double dlnow=0.0)
Definition: MediaCurl2.cc:86
The NetworkRequestError class Represents a error that occured in.
zyppng::NetworkRequestDispatcherRef _nwDispatcher
Definition: MediaCurl2.h:129
shared_ptr< AuthData > AuthData_Ptr
Definition: authdata.h:81
const long & ZYPP_MEDIA_CURL_DEBUG()
const long& for setting CURLOPT_DEBUGDATA Returns a reference to a static variable, so it&#39;s safe to pass ...
Definition: curlhelper.cc:36
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
void fillSettingsFromUrl(const Url &url, media::TransferSettings &s)
Fills the settings structure using options passed on the url for example ?timeout=x&proxy=foo.
Definition: curlhelper.cc:183
bool checkAttachPoint(const Pathname &apoint) const override
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
Definition: MediaCurl2.cc:248
void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const override
Call concrete handler to provide a content list of directory on media via retlist.
Definition: MediaCurl2.cc:574
bool isValid() const
Verifies the Url.
Definition: Url.cc:507
static Ptr create()
const Pathname & filename() const
The path to the resource on the medium.
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:705
to not add a IFMODSINCE header if target exists
Definition: MediaCurl2.h:50
const zypp::Pathname & targetFilePath() const
Returns the target filename path.
Definition: request.cc:919
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:37
void getDir(const Pathname &dirname, bool recurse_r) const override
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition: MediaCurl2.cc:541
void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition: MediaCurl2.cc:223
const Pathname & deltafile() const
The existing deltafile that can be used to reduce download size ( zchunk or metalink ) ...
#define WAR_MEDIA
Definition: mediadebug_p.h:30
Pathname absolutename() const
Return this path, adding a leading &#39;/&#39; if relative.
Definition: Pathname.h:141
Base class for Exception.
Definition: Exception.h:146
Pathname attachPoint() const
Return the currently used attach point.
Url url() const
Url used.
Definition: MediaHandler.h:503
shared_ptr< CurlAuthData > CurlAuthData_Ptr
Definition: curlauthdata.h:102
static bool validateZckFile(const zypp::Pathname &file, std::string &error)
Definition: zckhelper.cc:169
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:622
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition: Url.cc:606
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:225
Url clearQueryString(const Url &url) const
Definition: MediaCurl2.cc:164
SignalProxy< void(NetworkRequest &req, const NetworkRequestError &err)> sigFinished()
Signals that the download finished.
Definition: request.cc:1066
void fillSettingsSystemProxy(const Url &url, media::TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Definition: curlhelper.cc:338
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition: PathInfo.h:806
int rename(const Pathname &oldpath, const Pathname &newpath)
Like &#39;rename&#39;.
Definition: PathInfo.cc:747
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
Curl HTTP authentication data.
Definition: curlauthdata.h:22
virtual void doGetFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename, callback::SendReport< DownloadProgressReport > &_report, RequestOptions options=OPTION_NONE) const
Definition: MediaCurl2.cc:355
const std::string & proxy() const
proxy host
void checkProtocol(const Url &url) const
check the url is supported by the curl library
Definition: MediaCurl2.cc:171
std::chrono::steady_clock clock
Definition: MediaCurl2.cc:72
SignalProxy< void(NetworkRequest &req, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow)> sigProgress()
Signals if there was data read from the download.
Definition: request.cc:1061
int rmdir(const Pathname &path)
Like &#39;rmdir&#39;.
Definition: PathInfo.cc:371
bool optional() const
Whether this is an optional resource.
bool userMayRWX() const
Definition: PathInfo.h:361
Url manipulation class.
Definition: Url.h:92
void releaseFrom(const std::string &ejectDev) override
Call concrete handler to release the media.
Definition: MediaCurl2.cc:261
#define DBG
Definition: Logger.h:99
const CheckSum & headerChecksum() const
The checksum of the header prepending the resource (e.g.
static PrepareResult prepareZck(const zypp::Pathname &delta, const zypp::Pathname &target, const zypp::ByteCount &expectedFileSize)
Definition: zckhelper.cc:34
void getFile(const OnMediaLocation &file) const override
Call concrete handler to provide file below attach point.
Definition: MediaCurl2.cc:268
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
Definition: Url.cc:590