libzypp 17.32.2
MediaCurl.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 <utility>
22#include <zypp-core/parser/Sysconfig>
23#include <zypp/base/Gettext.h>
24
26#include <zypp-core/zyppng/base/private/linuxhelpers_p.h>
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
38#include <cstdlib>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <sys/mount.h>
42#include <dirent.h>
43#include <unistd.h>
44#include <glib.h>
45
46using std::endl;
47
48namespace internal {
49 using namespace zypp;
53 struct OptionalDownloadProgressReport : public callback::ReceiveReport<media::DownloadProgressReport>
54 {
55 using TimePoint = std::chrono::steady_clock::time_point;
56
57 OptionalDownloadProgressReport( bool isOptional=false )
58 : _oldRec { Distributor::instance().getReceiver() }
59 , _isOptional { isOptional }
60 { connect(); }
61
66
68 if (_oldRec)
69 Distributor::instance().setReceiver(*_oldRec);
70 else
71 Distributor::instance().noReceiver();
72 }
73
74 void reportbegin() override
75 { if ( _oldRec ) _oldRec->reportbegin(); }
76
77 void reportend() override
78 { if ( _oldRec ) _oldRec->reportend(); }
79
80 void report( const UserData & userData_r = UserData() ) override
81 { if ( _oldRec ) _oldRec->report( userData_r ); }
82
83
84 void start( const Url & file_r, Pathname localfile_r ) override
85 {
86 if ( not _oldRec ) return;
87 if ( _isOptional ) {
88 // delay start until first data are received.
90 _startLocalfile = std::move(localfile_r);
91 return;
92 }
94 }
95
96 bool progress( int value_r, const Url & file_r, double dbps_avg_r = -1, double dbps_current_r = -1 ) override
97 {
98 if ( not _oldRec ) return true;
99 if ( notStarted() ) {
100 if ( not ( value_r || dbps_avg_r || dbps_current_r ) )
101 return true;
102 sendStart();
103 }
104
105 //static constexpr std::chrono::milliseconds minfequency { 1000 }; only needed if we'd avoid sending reports without change
106 static constexpr std::chrono::milliseconds maxfequency { 100 };
107 TimePoint now { TimePoint::clock::now() };
108 TimePoint::duration elapsed { now - _lastProgressSent };
109 if ( elapsed < maxfequency )
110 return true; // continue
111 _lastProgressSent = now;
113 }
114
115 Action problem( const Url & file_r, Error error_r, const std::string & description_r ) override
116 {
117 if ( not _oldRec || notStarted() ) return ABORT;
119 }
120
121 void finish( const Url & file_r, Error error_r, const std::string & reason_r ) override
122 {
123 if ( not _oldRec || notStarted() ) return;
125 }
126
127 private:
128 // _isOptional also indicates the delayed start
129 bool notStarted() const
130 { return _isOptional; }
131
133 {
134 if ( _isOptional ) {
135 // we know _oldRec is valid...
136 _oldRec->start( _startFile, std::move(_startLocalfile) );
137 _isOptional = false;
138 }
139 }
140
141 private:
147 };
148
150 {
151 ProgressData( CURL *curl, time_t timeout = 0, zypp::Url url = zypp::Url(),
154
155 void updateStats( curl_off_t dltotal = 0.0, curl_off_t dlnow = 0.0 );
156
157 int reportProgress() const;
158
160 { return _curl; }
161
162 bool timeoutReached() const
163 { return _timeoutReached; }
164
165 bool fileSizeExceeded() const
166 { return _fileSizeExceeded; }
167
170
173
174 private:
177 time_t _timeout;
182
183 time_t _timeStart = 0;
184 time_t _timeLast = 0;
185 time_t _timeRcv = 0;
186 time_t _timeNow = 0;
187
188 curl_off_t _dnlTotal = 0.0;
189 curl_off_t _dnlLast = 0.0;
190 curl_off_t _dnlNow = 0.0;
191
192 int _dnlPercent= 0;
193
194 double _drateTotal= 0.0;
195 double _drateLast = 0.0;
196 };
197
198
199
201 : _curl( curl )
202 , _url(std::move( url ))
203 , _timeout( timeout )
204 , _timeoutReached( false )
205 , _fileSizeExceeded ( false )
206 , _expectedFileSize( expectedFileSize_r )
207 , report( _report )
208 {}
209
210 void ProgressData::updateStats( curl_off_t dltotal, curl_off_t dlnow )
211 {
212 time_t now = _timeNow = time(0);
213
214 // If called without args (0.0), recompute based on the last values seen
215 if ( dltotal && dltotal != _dnlTotal )
217
218 if ( dlnow && dlnow != _dnlNow )
219 {
220 _timeRcv = now;
221 _dnlNow = dlnow;
222 }
223
224 // init or reset if time jumps back
225 if ( !_timeStart || _timeStart > now )
226 _timeStart = _timeLast = _timeRcv = now;
227
228 // timeout condition
229 if ( _timeout )
230 _timeoutReached = ( (now - _timeRcv) > _timeout );
231
232 // check if the downloaded data is already bigger than what we expected
234
235 // percentage:
236 if ( _dnlTotal )
237 _dnlPercent = int( _dnlNow * 100 / _dnlTotal );
238
239 // download rates:
240 _drateTotal = double(_dnlNow) / std::max( int(now - _timeStart), 1 );
241
242 if ( _timeLast < now )
243 {
244 _drateLast = double(_dnlNow - _dnlLast) / int(now - _timeLast);
245 // start new period
246 _timeLast = now;
248 }
249 else if ( _timeStart == _timeLast )
251 }
252
254 {
255 if ( _fileSizeExceeded )
256 return 1;
257 if ( _timeoutReached )
258 return 1; // no-data timeout
259 if ( report && !(*report)->progress( _dnlPercent, _url, _drateTotal, _drateLast ) )
260 return 1; // user requested abort
261 return 0;
262 }
263
264 const char * anonymousIdHeader()
265 {
266 // we need to add the release and identifier to the
267 // agent string.
268 // The target could be not initialized, and then this information
269 // is guessed.
270 // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space
271 static const std::string _value( str::trim( str::form(
272 "X-ZYpp-AnonymousId: %s",
273 Target::anonymousUniqueId( Pathname()/*guess root*/ ).c_str()
274 )));
275 return _value.c_str();
276 }
277
279 {
280 // we need to add the release and identifier to the
281 // agent string.
282 // The target could be not initialized, and then this information
283 // is guessed.
284 // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space
285 static const std::string _value( str::trim( str::form(
286 "X-ZYpp-DistributionFlavor: %s",
287 Target::distributionFlavor( Pathname()/*guess root*/ ).c_str()
288 )));
289 return _value.c_str();
290 }
291
292 const char * agentString()
293 {
294 // we need to add the release and identifier to the
295 // agent string.
296 // The target could be not initialized, and then this information
297 // is guessed.
298 // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space
299 static const std::string _value( str::trim( str::form(
300 "ZYpp " LIBZYPP_VERSION_STRING " (curl %s) %s"
302 , Target::targetDistribution( Pathname()/*guess root*/ ).c_str()
303 )));
304 return _value.c_str();
305 }
306
311 {
312 public:
314 const std::string & err_r,
315 const std::string & msg_r )
316 : media::MediaCurlException( url_r, err_r, msg_r )
317 {}
318 //~MediaCurlExceptionMayRetryInternaly() noexcept {}
319 };
320
321}
322
323
324using namespace internal;
325using namespace zypp::base;
326
327namespace zypp {
328
329 namespace media {
330
331Pathname MediaCurl::_cookieFile = "/var/lib/YaST2/cookies";
332
333// we use this define to unbloat code as this C setting option
334// and catching exception is done frequently.
336#define SET_OPTION(opt,val) do { \
337 ret = curl_easy_setopt ( _curl, opt, val ); \
338 if ( ret != 0) { \
339 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); \
340 } \
341 } while ( false )
342
343#define SET_OPTION_OFFT(opt,val) SET_OPTION(opt,(curl_off_t)val)
344#define SET_OPTION_LONG(opt,val) SET_OPTION(opt,(long)val)
345#define SET_OPTION_VOID(opt,val) SET_OPTION(opt,(void*)val)
346
350 "/", // urlpath at attachpoint
351 true ), // does_download
352 _curl( NULL ),
353 _customHeaders(0L)
354{
355 _curlError[0] = '\0';
356
357 MIL << "MediaCurl::MediaCurl(" << url_r << ", " << attach_point_hint_r << ")" << endl;
358
360
361 if( !attachPoint().empty())
362 {
364 Pathname apath(attachPoint() + "XXXXXX");
365 char *atemp = ::strdup( apath.asString().c_str());
366 char *atest = NULL;
367 if( !ainfo.isDir() || !ainfo.userMayRWX() ||
368 atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
369 {
370 WAR << "attach point " << ainfo.path()
371 << " is not useable for " << url_r.getScheme() << endl;
372 setAttachPoint("", true);
373 }
374 else if( atest != NULL)
375 ::rmdir(atest);
376
377 if( atemp != NULL)
378 ::free(atemp);
379 }
380}
381
383{
385}
386
391
393
394void MediaCurl::checkProtocol(const Url &url) const
395{
398 // curl_info does not need any free (is static)
399 if (curl_info->protocols)
400 {
401 const char * const *proto = nullptr;
402 std::string scheme( url.getScheme());
403 bool found = false;
404 for(proto=curl_info->protocols; !found && *proto; ++proto)
405 {
406 if( scheme == std::string((const char *)*proto))
407 found = true;
408 }
409 if( !found)
410 {
411 std::string msg("Unsupported protocol '");
412 msg += scheme;
413 msg += "'";
415 }
416 }
417}
418
420{
422
426 if ( ret != 0 ) {
427 ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer"));
428 }
429
432
433 // create non persistant settings
434 // so that we don't add headers twice
436
437 // add custom headers for download.opensuse.org (bsc#955801)
438 if ( _url.getHost() == "download.opensuse.org" )
439 {
440 vol_settings.addHeader(anonymousIdHeader());
442 }
443 vol_settings.addHeader("Pragma:");
444
446
447 // fill some settings from url query parameters
448 try
449 {
451 }
452 catch ( const MediaException &e )
453 {
456 }
457 // if the proxy was not set (or explicitly unset) by url, then look...
458 if ( _settings.proxy().empty() )
459 {
460 // ...at the system proxy settings
462 }
463
466 {
469 }
470
475 // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit
476 // just in case curl does not trigger its progress callback frequently
477 // enough.
478 if ( _settings.timeout() )
479 {
481 }
482
483 // follow any Location: header that the server sends as part of
484 // an HTTP header (#113275)
486 // 3 redirects seem to be too few in some cases (bnc #465532)
488
489 if ( _url.getScheme() == "https" )
490 {
493 }
494
497 {
499 }
500
502 {
504 }
505 if( ! _settings.clientKeyPath().empty() )
506 {
508 }
509
510#ifdef CURLSSLOPT_ALLOW_BEAST
511 // see bnc#779177
513 if ( ret != 0 ) {
516 }
517#endif
520 // bnc#903405 - POODLE: libzypp should only talk TLS
522 }
523
525
526 /* Fixes bsc#1174011 "auth=basic ignored in some cases"
527 * We should proactively add the password to the request if basic auth is configured
528 * and a password is available in the credentials but not in the URL.
529 *
530 * We will be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route
531 * and ask the server first about the auth method
532 */
533 if ( _settings.authType() == "basic"
534 && _settings.username().size()
535 && !_settings.password().size() ) {
536
538 const auto cred = cm.getCred( _url );
539 if ( cred && cred->valid() ) {
540 if ( !_settings.username().size() )
541 _settings.setUsername(cred->username());
542 _settings.setPassword(cred->password());
543 }
544 }
545
546 /*---------------------------------------------------------------*
547 CURLOPT_USERPWD: [user name]:[password]
548
549 Url::username/password -> CURLOPT_USERPWD
550 If not provided, anonymous FTP identification
551 *---------------------------------------------------------------*/
552
553 if ( _settings.userPassword().size() )
554 {
556 std::string use_auth = _settings.authType();
557 if (use_auth.empty())
558 use_auth = "digest,basic"; // our default
560 if( auth != CURLAUTH_NONE)
561 {
562 DBG << "Enabling HTTP authentication methods: " << use_auth
563 << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl;
565 }
566 }
567
568 if ( _settings.proxyEnabled() && ! _settings.proxy().empty() )
569 {
570 DBG << "Proxy: '" << _settings.proxy() << "'" << endl;
573 /*---------------------------------------------------------------*
574 * CURLOPT_PROXYUSERPWD: [user name]:[password]
575 *
576 * Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD
577 * If not provided, $HOME/.curlrc is evaluated
578 *---------------------------------------------------------------*/
579
580 std::string proxyuserpwd = _settings.proxyUserPassword();
581
582 if ( proxyuserpwd.empty() )
583 {
585 CurlConfig::parseConfig(curlconf); // parse ~/.curlrc
586 if ( curlconf.proxyuserpwd.empty() )
587 DBG << "Proxy: ~/.curlrc does not contain the proxy-user option" << endl;
588 else
589 {
590 proxyuserpwd = curlconf.proxyuserpwd;
591 DBG << "Proxy: using proxy-user from ~/.curlrc" << endl;
592 }
593 }
594 else
595 {
596 DBG << "Proxy: using provided proxy-user '" << _settings.proxyUsername() << "'" << endl;
597 }
598
599 if ( ! proxyuserpwd.empty() )
600 {
601 SET_OPTION(CURLOPT_PROXYUSERPWD, curlUnEscape( proxyuserpwd ).c_str());
602 }
603 }
604#if CURLVERSION_AT_LEAST(7,19,4)
605 else if ( _settings.proxy() == EXPLICITLY_NO_PROXY )
606 {
607 // Explicitly disabled in URL (see fillSettingsFromUrl()).
608 // This should also prevent libcurl from looking into the environment.
609 DBG << "Proxy: explicitly NOPROXY" << endl;
611 }
612#endif
613 else
614 {
615 DBG << "Proxy: not explicitly set" << endl;
616 DBG << "Proxy: libcurl may look into the environment" << endl;
617 }
618
620 if ( _settings.minDownloadSpeed() != 0 )
621 {
623 // default to 10 seconds at low speed
625 }
626
627#if CURLVERSION_AT_LEAST(7,15,5)
628 if ( _settings.maxDownloadSpeed() != 0 )
630#endif
631
632 /*---------------------------------------------------------------*
633 *---------------------------------------------------------------*/
634
635 _currentCookieFile = _cookieFile.asString();
636 if ( ::geteuid() == 0 || PathInfo(_currentCookieFile).owner() == ::geteuid() )
638
639 const auto &cookieFileParam = _url.getQueryParam( "cookies" );
640 if ( !cookieFileParam.empty() && str::strToBool( cookieFileParam, true ) )
642 else
643 MIL << "No cookies requested" << endl;
647
648#if CURLVERSION_AT_LEAST(7,18,0)
649 // bnc #306272
651#endif
652 // Append settings custom headers to curl.
653 // TransferSettings assert strings are trimmed (HTTP/2 RFC 9113)
654 for ( const auto &header : vol_settings.headers() ) {
656 if ( !_customHeaders )
658 }
660}
661
663
664
665void MediaCurl::attachTo (bool next)
666{
667 if ( next )
669
670 if ( !_url.isValid() )
672
675 {
677 }
678
679 disconnectFrom(); // clean _curl if needed
681 if ( !_curl ) {
683 }
684 try
685 {
686 setupEasy();
687 }
688 catch (Exception & ex)
689 {
692 }
693
694 // FIXME: need a derived class to propelly compare url's
696 setMediaSource(media);
697}
698
699bool
701{
702 return MediaHandler::checkAttachPoint( apoint, true, true);
703}
704
706
708{
709 if ( _customHeaders )
710 {
712 _customHeaders = 0L;
713 }
714
715 if ( _curl )
716 {
717 // bsc#1201092: Strange but within global_dtors we may exceptions here.
718 try { curl_easy_cleanup( _curl ); }
719 catch (...) { ; }
720 _curl = NULL;
721 }
722}
723
725
726void MediaCurl::releaseFrom( const std::string & ejectDev )
727{
728 disconnect();
729}
730
732
733void MediaCurl::getFile( const OnMediaLocation &file ) const
734{
735 // Use absolute file name to prevent access of files outside of the
736 // hierarchy below the attach point.
737 getFileCopy( file, localPath(file.filename()).absolutename() );
738}
739
741
742void MediaCurl::getFileCopy( const OnMediaLocation & srcFile , const Pathname & target ) const
743{
744
745 const auto &filename = srcFile.filename();
746
747 // Optional files will send no report until data are actually received (we know it exists).
750
751 Url fileurl(getFileUrl(filename));
752
753 bool firstAuth = true; // bsc#1210870: authenticate must not return stored credentials more than once.
754 unsigned internalTry = 0;
755 static constexpr unsigned maxInternalTry = 3;
756
757 do
758 {
759 try
760 {
761 doGetFileCopy( srcFile, target, report );
762 break; // success!
763 }
764 // retry with proper authentication data
766 {
767 if ( authenticate(ex_r.hint(), firstAuth) ) {
768 firstAuth = false; // must not return stored credentials again
769 continue; // retry
770 }
771
772 report->finish(fileurl, zypp::media::DownloadProgressReport::ACCESS_DENIED, ex_r.asUserHistory());
774 }
775 // unexpected exception
776 catch (MediaException & excpt_r)
777 {
778 if ( typeid(excpt_r) == typeid( MediaCurlExceptionMayRetryInternaly ) ) {
779 ++internalTry;
780 if ( internalTry < maxInternalTry ) {
781 // just report (NO_ERROR); no interactive request to the user
782 report->problem(fileurl, media::DownloadProgressReport::NO_ERROR, excpt_r.asUserHistory()+_("Will try again..."));
783 continue; // retry
784 }
785 excpt_r.addHistory( str::Format(_("Giving up after %1% attempts.")) % maxInternalTry );
786 }
787
789 if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) ||
790 typeid(excpt_r) == typeid( media::MediaNotAFileException ) )
791 {
793 }
794 report->finish(fileurl, reason, excpt_r.asUserHistory());
796 }
797 }
798 while ( true );
800}
801
803
804bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
805{
806 bool retry = false;
807
808 do
809 {
810 try
811 {
812 return doGetDoesFileExist( filename );
813 }
814 // authentication problem, retry with proper authentication data
816 {
817 if(authenticate(ex_r.hint(), !retry))
818 retry = true;
819 else
821 }
822 // unexpected exception
823 catch (MediaException & excpt_r)
824 {
826 }
827 }
828 while (retry);
829
830 return false;
831}
832
834
836 CURLcode code,
837 bool timeout_reached) const
838{
839 if ( code != 0 )
840 {
841 Url url;
842 if (filename.empty())
843 url = _url;
844 else
845 url = getFileUrl(filename);
846
847 std::string err;
848 {
849 switch ( code )
850 {
852 err = " Unsupported protocol";
853 if ( !_lastRedirect.empty() )
854 {
855 err += " or redirect (";
856 err += _lastRedirect;
857 err += ")";
858 }
859 break;
862 err = " Bad URL";
863 break;
866 MediaUnauthorizedException(url, "Login failed.", _curlError, ""));
867 break;
869 {
870 long httpReturnCode = 0;
874 if ( infoRet == CURLE_OK )
875 {
876 std::string msg = "HTTP response: " + str::numstring( httpReturnCode );
877 switch ( httpReturnCode )
878 {
879 case 401:
880 {
881 std::string auth_hint = getAuthHint();
882
883 DBG << msg << " Login failed (URL: " << url.asString() << ")" << std::endl;
884 DBG << "MediaUnauthorizedException auth hint: '" << auth_hint << "'" << std::endl;
885
887 url, "Login failed.", _curlError, auth_hint
888 ));
889 }
890
891 case 502: // bad gateway (bnc #1070851)
892 case 503: // service temporarily unavailable (bnc #462545)
894 case 504: // gateway timeout
896 case 403:
897 {
898 std::string msg403;
899 if ( url.getHost().find(".suse.com") != std::string::npos )
900 msg403 = _("Visit the SUSE Customer Center to check whether your registration is valid and has not expired.");
901 else if (url.asString().find("novell.com") != std::string::npos)
902 msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired.");
904 }
905 case 404:
906 case 410:
908 }
909
910 DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
912 }
913 else
914 {
915 std::string msg = "Unable to retrieve HTTP response:";
916 DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
918 }
919 }
920 break;
922#if CURLVERSION_AT_LEAST(7,16,0)
924#endif
927 err = "File not found";
929 break;
932 err = "Login failed";
933 break;
938 err = "Connection failed";
939 break;
941 err = "Write error";
942 break;
945 timeout_reached = true; // fall though to TimeoutException
946 // fall though...
948 if( timeout_reached )
949 {
950 err = "Timeout reached";
952 }
953 else
954 {
955 err = "User abort";
956 }
957 break;
958
959 // Attempt to work around certain issues by autoretry in MediaCurl::getFileCopy
960 case CURLE_HTTP2:
962 err = "Curl error " + str::numstring( code );
964 break;
965
966 default:
967 err = "Curl error " + str::numstring( code );
968 break;
969 }
970
971 // uhm, no 0 code but unknown curl exception
973 }
974 }
975 else
976 {
977 // actually the code is 0, nothing happened
978 }
979}
980
982
983bool MediaCurl::doGetDoesFileExist( const Pathname & filename ) const
984{
985 DBG << filename.asString() << endl;
986
987 if(!_url.isValid())
989
990 if(_url.getHost().empty())
992
993 Url url(getFileUrl(filename));
994
995 DBG << "URL: " << url.asString() << endl;
996 // Use URL without options and without username and passwd
997 // (some proxies dislike them in the URL).
998 // Curl seems to need the just scheme, hostname and a path;
999 // the rest was already passed as curl options (in attachTo).
1001
1002 //
1003 // See also Bug #154197 and ftp url definition in RFC 1738:
1004 // The url "ftp://user@host/foo/bar/file" contains a path,
1005 // that is relative to the user's home.
1006 // The url "ftp://user@host//foo/bar/file" (or also with
1007 // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
1008 // contains an absolute path.
1009 //
1010 _lastRedirect.clear();
1011 std::string urlBuffer( curlUrl.asString());
1013 urlBuffer.c_str() );
1014 if ( ret != 0 ) {
1016 }
1017
1018 // If no head requests allowed (?head_requests=no):
1019 // Instead of returning no data with NOBODY, we return
1020 // little data, that works with broken servers, and
1021 // works for ftp as well, because retrieving only headers
1022 // ftp will return always OK code ?
1023 // See http://curl.haxx.se/docs/knownbugs.html #58
1025 struct TempSetHeadRequest
1026 {
1029 if ( _doHttpHeadRequest ) {
1030 curl_easy_setopt( _curl, CURLOPT_NOBODY, 1L );
1031 } else {
1032 curl_easy_setopt( _curl, CURLOPT_RANGE, "0-1" );
1033 }
1034 }
1035 TempSetHeadRequest(const TempSetHeadRequest &) = delete;
1037 TempSetHeadRequest &operator=(const TempSetHeadRequest &) = delete;
1038 TempSetHeadRequest &operator=(TempSetHeadRequest &&) = delete;
1040 if ( _doHttpHeadRequest ) {
1042 /* yes, this is why we never got to get NOBODY working before,
1043 because setting it changes this option too, and we also*
1044 need to reset it
1045 See: http://curl.haxx.se/mail/archive-2005-07/0073.html
1046 */
1047 curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
1048 } else {
1050 }
1051 }
1052 private:
1053 CURL * _curl;
1054 bool _doHttpHeadRequest;
1055 } _guard( _curl, (_url.getScheme() == "http" || _url.getScheme() == "https") && _settings.headRequestsAllowed() );
1056
1057
1058 AutoFILE file { ::fopen( "/dev/null", "w" ) };
1059 if ( !file ) {
1060 ERR << "fopen failed for /dev/null" << endl;
1061 ZYPP_THROW(MediaWriteException("/dev/null"));
1062 }
1063
1065 if ( ret != 0 ) {
1067 }
1068
1070 MIL << "perform code: " << ok << " [ " << curl_easy_strerror(ok) << " ]" << endl;
1071
1072 // as we are not having user interaction, the user can't cancel
1073 // the file existence checking, a callback or timeout return code
1074 // will be always a timeout.
1075 try {
1076 evaluateCurlCode( filename, ok, true /* timeout */);
1077 }
1078 catch ( const MediaFileNotFoundException &e ) {
1079 // if the file did not exist then we can return false
1080 return false;
1081 }
1082 catch ( const MediaException &e ) {
1083 // some error, we are not sure about file existence, rethrw
1084 ZYPP_RETHROW(e);
1085 }
1086 // exists
1087 return ( ok == CURLE_OK );
1088}
1089
1091
1093{
1094 Pathname dest = target.absolutename();
1095 if( assert_dir( dest.dirname() ) )
1096 {
1097 DBG << "assert_dir " << dest.dirname() << " failed" << endl;
1098 ZYPP_THROW( MediaSystemException(getFileUrl(srcFile.filename()), "System error on " + dest.dirname().asString()) );
1099 }
1100
1101 ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) };
1102 AutoFILE file;
1103 {
1104 AutoFREE<char> buf { ::strdup( (*destNew).c_str() ) };
1105 if( ! buf )
1106 {
1107 ERR << "out of memory for temp file name" << endl;
1108 ZYPP_THROW(MediaSystemException(getFileUrl(srcFile.filename()), "out of memory for temp file name"));
1109 }
1110
1112 if( tmp_fd == -1 )
1113 {
1114 ERR << "mkstemp failed for file '" << destNew << "'" << endl;
1116 }
1118
1119 file = ::fdopen( tmp_fd, "we" );
1120 if ( ! file )
1121 {
1122 ERR << "fopen failed for file '" << destNew << "'" << endl;
1124 }
1125 tmp_fd.resetDispose(); // don't close it here! ::fdopen moved ownership to file
1126 }
1127
1128 DBG << "dest: " << dest << endl;
1129 DBG << "temp: " << destNew << endl;
1130
1131 // set IFMODSINCE time condition (no download if not modified)
1132 if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) )
1133 {
1135 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime());
1136 }
1137 else
1138 {
1141 }
1142 try
1143 {
1144 doGetFileCopyFile( srcFile, dest, file, report, options);
1145 }
1146 catch (Exception &e)
1147 {
1150 ZYPP_RETHROW(e);
1151 }
1152
1153 long httpReturnCode = 0;
1157 bool modified = true;
1158 if (infoRet == CURLE_OK)
1159 {
1160 DBG << "HTTP response: " + str::numstring(httpReturnCode);
1161 if ( httpReturnCode == 304
1162 || ( httpReturnCode == 213 && (_url.getScheme() == "ftp" || _url.getScheme() == "tftp") ) ) // not modified
1163 {
1164 DBG << " Not modified.";
1165 modified = false;
1166 }
1167 DBG << endl;
1168 }
1169 else
1170 {
1171 WAR << "Could not get the response code." << endl;
1172 }
1173
1174 if (modified || infoRet != CURLE_OK)
1175 {
1176 // apply umask
1177 if ( ::fchmod( ::fileno(file), filesystem::applyUmaskTo( 0644 ) ) )
1178 {
1179 ERR << "Failed to chmod file " << destNew << endl;
1180 }
1181
1182 file.resetDispose(); // we're going to close it manually here
1183 if ( ::fclose( file ) )
1184 {
1185 ERR << "Fclose failed for file '" << destNew << "'" << endl;
1187 }
1188
1189 // move the temp file into dest
1190 if ( rename( destNew, dest ) != 0 ) {
1191 ERR << "Rename failed" << endl;
1193 }
1194 destNew.resetDispose(); // no more need to unlink it
1195 }
1196
1197 DBG << "done: " << PathInfo(dest) << endl;
1198}
1199
1201
1203{
1204 DBG << srcFile.filename().asString() << endl;
1205
1206 if(!_url.isValid())
1208
1209 if(_url.getHost().empty())
1211
1212 Url url(getFileUrl(srcFile.filename()));
1213
1214 DBG << "URL: " << url.asString() << endl;
1215 // Use URL without options and without username and passwd
1216 // (some proxies dislike them in the URL).
1217 // Curl seems to need the just scheme, hostname and a path;
1218 // the rest was already passed as curl options (in attachTo).
1220
1221 //
1222 // See also Bug #154197 and ftp url definition in RFC 1738:
1223 // The url "ftp://user@host/foo/bar/file" contains a path,
1224 // that is relative to the user's home.
1225 // The url "ftp://user@host//foo/bar/file" (or also with
1226 // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
1227 // contains an absolute path.
1228 //
1229 _lastRedirect.clear();
1230 std::string urlBuffer( curlUrl.asString());
1232 urlBuffer.c_str() );
1233 if ( ret != 0 ) {
1235 }
1236
1238 if ( ret != 0 ) {
1240 }
1241
1242 // Set callback and perform.
1244 if (!(options & OPTION_NO_REPORT_START))
1245 report->start(url, dest);
1247 WAR << "Can't set CURLOPT_PROGRESSDATA: " << _curlError << endl;;
1248 }
1249
1250 ret = executeCurl();
1251#if CURLVERSION_AT_LEAST(7,19,4)
1252 // bnc#692260: If the client sends a request with an If-Modified-Since header
1253 // with a future date for the server, the server may respond 200 sending a
1254 // zero size file.
1255 // curl-7.19.4 introduces CURLINFO_CONDITION_UNMET to check this condition.
1256 if ( ftell(file) == 0 && ret == 0 )
1257 {
1258 long httpReturnCode = 33;
1260 {
1261 long conditionUnmet = 33;
1263 {
1264 WAR << "TIMECONDITION unmet - retry without." << endl;
1267 ret = executeCurl();
1268 }
1269 }
1270 }
1271#endif
1272
1274 WAR << "Can't unset CURLOPT_PROGRESSDATA: " << _curlError << endl;;
1275 }
1276
1277 if ( ret != 0 )
1278 {
1279 ERR << "curl error: " << ret << ": " << _curlError
1280 << ", temp file size " << ftell(file)
1281 << " bytes." << endl;
1282
1283 // the timeout is determined by the progress data object
1284 // which holds whether the timeout was reached or not,
1285 // otherwise it would be a user cancel
1286 try {
1287
1288 if ( progressData.fileSizeExceeded() )
1290
1291 evaluateCurlCode( srcFile.filename(), ret, progressData.timeoutReached() );
1292 }
1293 catch ( const MediaException &e ) {
1294 // some error, we are not sure about file existence, rethrw
1295 ZYPP_RETHROW(e);
1296 }
1297 }
1298}
1299
1301
1302void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const
1303{
1304 filesystem::DirContent content;
1305 getDirInfo( content, dirname, /*dots*/false );
1306
1307 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1308 Pathname filename = dirname + it->name;
1309 int res = 0;
1310
1311 switch ( it->type ) {
1312 case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
1314 getFile( OnMediaLocation( filename ) );
1315 break;
1316 case filesystem::FT_DIR: // newer directory.yast contain at least directory info
1317 if ( recurse_r ) {
1318 getDir( filename, recurse_r );
1319 } else {
1320 res = assert_dir( localPath( filename ) );
1321 if ( res ) {
1322 WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl;
1323 }
1324 }
1325 break;
1326 default:
1327 // don't provide devices, sockets, etc.
1328 break;
1329 }
1330 }
1331}
1332
1334
1335void MediaCurl::getDirInfo( std::list<std::string> & retlist,
1336 const Pathname & dirname, bool dots ) const
1337{
1338 getDirectoryYast( retlist, dirname, dots );
1339}
1340
1342
1344 const Pathname & dirname, bool dots ) const
1345{
1346 getDirectoryYast( retlist, dirname, dots );
1347}
1348
1350//
1351int MediaCurl::aliveCallback( void *clientp, curl_off_t /*dltotal*/, curl_off_t dlnow, curl_off_t /*ultotal*/, curl_off_t /*ulnow*/ )
1352{
1354 if( pdata )
1355 {
1356 // Do not propagate dltotal in alive callbacks. MultiCurl uses this to
1357 // prevent a percentage raise while downloading a metalink file. Download
1358 // activity however is indicated by propagating the download rate (via dlnow).
1359 pdata->updateStats( 0.0, dlnow );
1360 return pdata->reportProgress();
1361 }
1362 return 0;
1363}
1364
1365int MediaCurl::progressCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow )
1366{
1368 if( pdata )
1369 {
1370 // work around curl bug that gives us old data
1371 long httpReturnCode = 0;
1374
1375 pdata->updateStats( dltotal, dlnow );
1376 return pdata->reportProgress();
1377 }
1378 return 0;
1379}
1380
1382{
1384 return pdata ? pdata->curl() : 0;
1385}
1386
1388
1389std::string MediaCurl::getAuthHint() const
1390{
1391 long auth_info = CURLAUTH_NONE;
1392
1395
1396 if(infoRet == CURLE_OK)
1397 {
1399 }
1400
1401 return "";
1402}
1403
1408void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
1409{
1410 internal::ProgressData *data = reinterpret_cast<internal::ProgressData *>(clientp);
1411 if ( data ) {
1412 data->expectedFileSize( expectedFileSize );
1413 }
1414}
1415
1422{
1423 // initialize our helpers
1426 ,[](auto &releaseMe ){ if (releaseMe._multi) curl_multi_cleanup(releaseMe._multi); }
1427 );
1428
1429 if (!cMulti->_multi)
1431
1432 // we could derive from that, but currently that does not make a lot of sense
1434
1435 // add the easy handle to the multi instance
1436 if ( curl_multi_add_handle( cMulti->_multi, _curl ) != CURLM_OK )
1437 ZYPP_THROW(MediaCurlException( _url, "curl_multi_add_handle", "unknown error"));
1438
1439 // make sure the handle is cleanly removed from the multi handle
1441
1442 // kickstart curl, this will cause libcurl to go over the added handles and register sockets and timeouts
1443 CURLMcode mcode = _curlHelper.handleTimout();
1444 if (mcode != CURLM_OK)
1445 ZYPP_THROW(MediaCurlException( _url, "curl_multi_socket_action", "unknown error"));
1446
1447 bool canContinue = true;
1448 while ( canContinue ) {
1449
1450 // copy watched sockets in case curl changes the vector as we go over the events later
1451 std::vector<GPollFD> requestedFds = _curlHelper.socks;
1452
1453 int r = zypp_detail::zypp_poll( requestedFds, _curlHelper.timeout_ms.value_or( -1 ) );
1454 if ( r == -1 )
1455 ZYPP_THROW( MediaCurlException(_url, "zypp_poll() failed", "unknown error") );
1456
1457 // run curl
1458 if ( r == 0 ) {
1459 CURLMcode mcode = _curlHelper.handleTimout();
1460 if (mcode != CURLM_OK)
1461 ZYPP_THROW(MediaCurlException(_url, "curl_multi_socket_action", "unknown error"));
1462 } else {
1463 CURLMcode mcode = _curlHelper.handleSocketActions( requestedFds );
1464 if (mcode != CURLM_OK)
1465 ZYPP_THROW(MediaCurlException(_url, "curl_multi_socket_action", "unknown error"));
1466 }
1467
1468 CURLMsg *msg = nullptr;
1469 int nqueue = 0;
1470 while ((msg = curl_multi_info_read( cMulti->_multi, &nqueue)) != 0) {
1471 if ( msg->msg != CURLMSG_DONE ) continue;
1472 if ( msg->easy_handle != _curl ) continue;
1473
1474 return msg->data.result;
1475 }
1476 }
1477 return CURLE_OK;
1478}
1479
1481
1482bool MediaCurl::authenticate(const std::string & availAuthTypes, bool firstTry) const
1483{
1487
1488 // get stored credentials
1489 AuthData_Ptr cmcred = cm.getCred(_url);
1490
1491 if (cmcred && firstTry)
1492 {
1494 DBG << "got stored credentials:" << endl << *credentials << endl;
1495 }
1496 // if not found, ask user
1497 else
1498 {
1499
1503
1504 // preset the username if present in current url
1505 if (!_url.getUsername().empty() && firstTry)
1506 curlcred->setUsername(_url.getUsername());
1507 // if CM has found some credentials, preset the username from there
1508 else if (cmcred)
1509 curlcred->setUsername(cmcred->username());
1510
1511 // indicate we have no good credentials from CM
1512 cmcred.reset();
1513
1514 std::string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString();
1515
1516 // set available authentication types from the exception
1517 // might be needed in prompt
1518 curlcred->setAuthType(availAuthTypes);
1519
1520 // ask user
1521 if (auth_report->prompt(_url, prompt_msg, *curlcred))
1522 {
1523 DBG << "callback answer: retry" << endl
1524 << "CurlAuthData: " << *curlcred << endl;
1525
1526 if (curlcred->valid())
1527 {
1529 // if (credentials->username() != _url.getUsername())
1530 // _url.setUsername(credentials->username());
1538 }
1539 }
1540 else
1541 {
1542 DBG << "callback answer: cancel" << endl;
1543 }
1544 }
1545
1546 // set username and password
1547 if (credentials)
1548 {
1549 // HACK, why is this const?
1550 const_cast<MediaCurl*>(this)->_settings.setUsername(credentials->username());
1551 const_cast<MediaCurl*>(this)->_settings.setPassword(credentials->password());
1552
1553 // set username and password
1556
1557 // set available authentication types from the exception
1558 if (credentials->authType() == CURLAUTH_NONE)
1559 credentials->setAuthType(availAuthTypes);
1560
1561 // set auth type (seems this must be set _after_ setting the userpwd)
1562 if (credentials->authType() != CURLAUTH_NONE)
1563 {
1564 // FIXME: only overwrite if not empty?
1565 const_cast<MediaCurl*>(this)->_settings.setAuthType(credentials->authTypeAsString());
1568 }
1569
1570 if (!cmcred)
1571 {
1572 credentials->setUrl(_url);
1573 cm.addCred(*credentials);
1574 cm.save();
1575 }
1576
1577 return true;
1578 }
1579
1580 return false;
1581}
1582
1583//need a out of line definiton, otherwise vtable is emitted for every translation unit
1585
1586 } // namespace media
1587} // namespace zypp
1588//
#define LIBZYPP_VERSION_STRING
Definition APIConfig.h:15
#define SET_OPTION_OFFT(opt, val)
Definition MediaCurl.cc:343
#define SET_OPTION(opt, val)
Definition MediaCurl.cc:336
Edition * _value
TrueBool _guard
Attempt to work around certain issues by autoretry in MediaCurl::getFileCopy E.g.
Definition MediaCurl.cc:311
MediaCurlExceptionMayRetryInternaly(const Url &url_r, const std::string &err_r, const std::string &msg_r)
Definition MediaCurl.cc:313
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
reference value() const
Reference to the Tp object.
void resetDispose()
Set no dispose function.
void reset()
Reset to default Ctor values.
Store and operate with byte count.
Definition ByteCount.h:31
Base class for Exception.
Definition Exception.h:147
const char * c_str() const
Describes a resource file located on a medium.
const Pathname & filename() const
The path to the resource on the medium.
ProgressData()
Ctor no range [0,0](0).
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
Definition Target.cc:127
std::string anonymousUniqueId() const
anonymous unique id
Definition Target.cc:132
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Definition Target.cc:102
Url manipulation class.
Definition Url.h:92
std::string getScheme() const
Returns the scheme name of the URL.
Definition Url.cc:537
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:501
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
Definition Url.cc:576
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:664
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition Url.cc:592
bool isValid() const
Verifies the Url.
Definition Url.cc:493
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:925
Typesafe passing of user data via callbacks.
Definition UserData.h:39
Wrapper class for stat/lstat.
Definition PathInfo.h:222
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition Pathname.h:173
const char * c_str() const
String representation.
Definition Pathname.h:110
const std::string & asString() const
String representation.
Definition Pathname.h:91
bool empty() const
Test for an empty path.
Definition Pathname.h:114
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Definition Pathname.h:139
Curl HTTP authentication data.
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_* ...
MediaCurlException(const Url &url_r, std::string err_r, std::string msg_r)
Implementation class for FTP, HTTP and HTTPS MediaHandler.
Definition MediaCurl.h:32
virtual void setupEasy()
initializes the curl easy handle with the data from the url
Definition MediaCurl.cc:419
static void setCookieFile(const Pathname &)
Definition MediaCurl.cc:387
bool getDoesFileExist(const Pathname &filename) const override
Repeatedly calls doGetDoesFileExist() until it successfully returns, fails unexpectedly,...
Definition MediaCurl.cc:804
@ OPTION_NO_IFMODSINCE
to not add a IFMODSINCE header if target exists
Definition MediaCurl.h:43
@ OPTION_NO_REPORT_START
do not send a start ProgressReport
Definition MediaCurl.h:45
void getFile(const OnMediaLocation &file) const override
Call concrete handler to provide file below attach point.
Definition MediaCurl.cc:733
static void resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
MediaMultiCurl needs to reset the expected filesize in case a metalink file is downloaded otherwise t...
std::string _currentCookieFile
Definition MediaCurl.h:163
static Pathname _cookieFile
Definition MediaCurl.h:164
static int progressCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
Callback reporting download progress.
void getFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename) const override
Definition MediaCurl.cc:742
virtual void doGetFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename, callback::SendReport< DownloadProgressReport > &_report, RequestOptions options=OPTION_NONE) const
std::string _lastRedirect
to log/report redirections
Definition MediaCurl.h:166
Url clearQueryString(const Url &url) const
Definition MediaCurl.cc:382
void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition MediaCurl.cc:665
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.
char _curlError[CURL_ERROR_SIZE]
Definition MediaCurl.h:170
void doGetFileCopyFile(const OnMediaLocation &srcFile, const Pathname &dest, FILE *file, callback::SendReport< DownloadProgressReport > &report, RequestOptions options=OPTION_NONE) const
void checkProtocol(const Url &url) const
check the url is supported by the curl library
Definition MediaCurl.cc:394
MediaCurl(const Url &url_r, const Pathname &attach_point_hint_r)
Definition MediaCurl.cc:347
CURLcode executeCurl() 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:835
bool checkAttachPoint(const Pathname &apoint) const override
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
Definition MediaCurl.cc:700
void getDir(const Pathname &dirname, bool recurse_r) const override
Call concrete handler to provide directory content (not recursive!) below attach point.
bool authenticate(const std::string &availAuthTypes, bool firstTry) const
static CURL * progressCallback_getcurl(void *clientp)
void releaseFrom(const std::string &ejectDev) override
Call concrete handler to release the media.
Definition MediaCurl.cc:726
static int aliveCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
Callback sending just an alive trigger to the UI, without stats (e.g.
void disconnectFrom() override
Definition MediaCurl.cc:707
virtual bool doGetDoesFileExist(const Pathname &filename) const
Definition MediaCurl.cc:983
curl_slist * _customHeaders
Definition MediaCurl.h:171
std::string getAuthHint() const
Return a comma separated list of available authentication methods supported by server.
Just inherits Exception to separate media exceptions.
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.
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.
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.
Common baseclass for MediaCurl and MediaNetwork.
Url getFileUrl(const Pathname &filename) const
concatenate the attach url and the filename to a complete download url
Media source internally used by MediaManager and MediaHandler.
Definition MediaSource.h:38
Holds transfer setting.
const std::string & password() const
auth password
long maxDownloadSpeed() const
Maximum download speed (bytes per second)
long connectTimeout() const
connection timeout
const std::string & authType() const
get the allowed authentication types
long timeout() const
transfer timeout
void setUsername(const std::string &val_r)
sets the auth username
const Pathname & clientCertificatePath() const
SSL client certificate file.
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.
const std::string & proxy() const
proxy host
const Pathname & clientKeyPath() const
SSL client key file.
void setUserAgentString(std::string &&val_r)
sets the user agent ie: "Mozilla v3" (trims)
std::string proxyUserPassword() const
returns the proxy user and password as a user:pass string
bool verifyHostEnabled() const
Whether to verify host for ssl.
const std::string & userAgentString() const
user agent string (trimmed)
void setPassword(const std::string &val_r)
sets the auth password
bool headRequestsAllowed() const
whether HEAD requests are allowed
bool proxyEnabled() const
proxy is enabled
const std::string & username() const
auth username
const std::string & proxyUsername() const
proxy auth username
void setAuthType(const std::string &val_r)
set the allowed authentication types
const Pathname & certificateAuthoritiesPath() const
SSL certificate authorities path ( default: /etc/ssl/certs )
bool verifyPeerEnabled() const
Whether to verify peer for ssl.
#define EXPLICITLY_NO_PROXY
zypp::callback::SendReport< zypp::KeyRingReport > _report
Definition keyringwf.cc:457
void fillSettingsFromUrl(const Url &url, media::TransferSettings &s)
Fills the settings structure using options passed on the url for example ?timeout=x&proxy=foo.
size_t log_redirects_curl(char *ptr, size_t size, size_t nmemb, void *userdata)
const char * anonymousIdHeader()
Definition MediaCurl.cc:264
void globalInitCurlOnce()
Definition curlhelper.cc:64
const char * distributionFlavorHeader()
Definition MediaCurl.cc:278
std::string curlUnEscape(const std::string &text_r)
void setupZYPP_MEDIA_CURL_DEBUG(CURL *curl)
Setup CURLOPT_VERBOSE and CURLOPT_DEBUGFUNCTION according to env::ZYPP_MEDIA_CURL_DEBUG.
CURLcode setCurlRedirProtocols(CURL *curl)
const char * agentString()
Definition MediaCurl.cc:292
void fillSettingsSystemProxy(const Url &url, media::TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Url clearQueryString(const Url &url)
Definition Arch.h:364
int ZYPP_MEDIA_CURL_IPRESOLVE()
4/6 to force IPv4/v6
Definition curlhelper.cc:45
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition PathInfo.h:789
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:701
std::list< DirEntry > DirContent
Returned by readdir.
Definition PathInfo.h:519
int assert_file_mode(const Pathname &path, unsigned mode)
Like assert_file but enforce mode even if the file already exists.
Definition PathInfo.cc:1203
shared_ptr< AuthData > AuthData_Ptr
Definition authdata.h:81
std::string numstring(char n, int w=0)
Definition String.h:289
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:429
std::string trim(const std::string &s, const Trim trim_r)
Definition String.cc:224
int zypp_poll(std::vector< GPollFD > &fds, int timeout)
Small wrapper around g_poll that additionally listens to the shutdown FD returned by ZYpp::shutdownSi...
Definition ZYppImpl.cc:313
Easy-to use interface to the ZYPP dependency resolver.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
Bottleneck filtering all DownloadProgressReport issued from Media[Muli]Curl.
Definition MediaCurl.cc:54
void report(const UserData &userData_r=UserData()) override
The most generic way of sending/receiving data.
Definition MediaCurl.cc:80
Action problem(const Url &file_r, Error error_r, const std::string &description_r) override
Definition MediaCurl.cc:115
OptionalDownloadProgressReport & operator=(const OptionalDownloadProgressReport &)=delete
OptionalDownloadProgressReport(bool isOptional=false)
Definition MediaCurl.cc:57
std::chrono::steady_clock::time_point TimePoint
Definition MediaCurl.cc:55
OptionalDownloadProgressReport(OptionalDownloadProgressReport &&)=delete
void finish(const Url &file_r, Error error_r, const std::string &reason_r) override
Definition MediaCurl.cc:121
bool progress(int value_r, const Url &file_r, double dbps_avg_r=-1, double dbps_current_r=-1) override
Download progress.
Definition MediaCurl.cc:96
OptionalDownloadProgressReport(const OptionalDownloadProgressReport &)=delete
void start(const Url &file_r, Pathname localfile_r) override
Definition MediaCurl.cc:84
ByteCount _expectedFileSize
Definition MediaCurl.cc:180
curl_off_t _dnlNow
Bytes downloaded now.
Definition MediaCurl.cc:190
int _dnlPercent
Percent completed or 0 if _dnlTotal is unknown.
Definition MediaCurl.cc:192
time_t _timeRcv
Start of no-data timeout.
Definition MediaCurl.cc:185
ByteCount expectedFileSize() const
Definition MediaCurl.cc:168
time_t _timeLast
Start last period(~1sec)
Definition MediaCurl.cc:184
int reportProgress() const
Definition MediaCurl.cc:253
double _drateLast
Download rate in last period.
Definition MediaCurl.cc:195
bool timeoutReached() const
Definition MediaCurl.cc:162
void expectedFileSize(ByteCount newval_r)
Definition MediaCurl.cc:171
curl_off_t _dnlLast
Bytes downloaded at period start.
Definition MediaCurl.cc:189
bool fileSizeExceeded() const
Definition MediaCurl.cc:165
void updateStats(curl_off_t dltotal=0.0, curl_off_t dlnow=0.0)
Definition MediaCurl.cc:210
double _drateTotal
Download rate so far.
Definition MediaCurl.cc:194
zypp::callback::SendReport< zypp::media::DownloadProgressReport > * report
Definition MediaCurl.cc:181
curl_off_t _dnlTotal
Bytes to download or 0 if unknown.
Definition MediaCurl.cc:188
time_t _timeStart
Start total stats.
Definition MediaCurl.cc:183
AutoDispose<int> calling ::close
AutoDispose<FILE*> calling ::fclose
virtual void report(const UserData &userData_r=UserData())
The most generic way of sending/receiving data.
Definition Callback.h:155
callback::UserData UserData
Definition Callback.h:151
Structure holding values of curlrc options.
Definition curlconfig.h:27
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
virtual void finish(const Url &, Error, const std::string &)
virtual bool progress(int, const Url &, double dbps_avg=-1, double dbps_current=-1)
Download progress.
virtual void start(const Url &, Pathname)
virtual Action problem(const Url &, Error, const std::string &)
Convenient building of std::string with boost::format.
Definition String.h:253
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:441
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:429
#define _(MSG)
Definition Gettext.h:37
#define DBG
Definition Logger.h:95
#define MIL
Definition Logger.h:96
#define ERR
Definition Logger.h:98
#define WAR
Definition Logger.h:97