libzypp 17.28.8
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
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
41using std::endl;
42
43using namespace internal;
44using namespace zypp::base;
45
46namespace zypp {
47
48 namespace media {
49
50Pathname MediaCurl::_cookieFile = "/var/lib/YaST2/cookies";
51
52// we use this define to unbloat code as this C setting option
53// and catching exception is done frequently.
55#define SET_OPTION(opt,val) do { \
56 ret = curl_easy_setopt ( _curl, opt, val ); \
57 if ( ret != 0) { \
58 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); \
59 } \
60 } while ( false )
61
62#define SET_OPTION_OFFT(opt,val) SET_OPTION(opt,(curl_off_t)val)
63#define SET_OPTION_LONG(opt,val) SET_OPTION(opt,(long)val)
64#define SET_OPTION_VOID(opt,val) SET_OPTION(opt,(void*)val)
65
67 const Pathname & attach_point_hint_r )
68 : MediaNetworkCommonHandler( url_r, attach_point_hint_r,
69 "/", // urlpath at attachpoint
70 true ), // does_download
71 _curl( NULL ),
72 _customHeaders(0L)
73{
74 _curlError[0] = '\0';
75 _curlDebug = 0L;
76
77 MIL << "MediaCurl::MediaCurl(" << url_r << ", " << attach_point_hint_r << ")" << endl;
78
80
81 if( !attachPoint().empty())
82 {
83 PathInfo ainfo(attachPoint());
84 Pathname apath(attachPoint() + "XXXXXX");
85 char *atemp = ::strdup( apath.asString().c_str());
86 char *atest = NULL;
87 if( !ainfo.isDir() || !ainfo.userMayRWX() ||
88 atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
89 {
90 WAR << "attach point " << ainfo.path()
91 << " is not useable for " << url_r.getScheme() << endl;
92 setAttachPoint("", true);
93 }
94 else if( atest != NULL)
95 ::rmdir(atest);
96
97 if( atemp != NULL)
98 ::free(atemp);
99 }
100}
101
103{
105}
106
107void MediaCurl::setCookieFile( const Pathname &fileName )
108{
109 _cookieFile = fileName;
110}
111
113
114void MediaCurl::checkProtocol(const Url &url) const
115{
116 curl_version_info_data *curl_info = NULL;
117 curl_info = curl_version_info(CURLVERSION_NOW);
118 // curl_info does not need any free (is static)
119 if (curl_info->protocols)
120 {
121 const char * const *proto;
122 std::string scheme( url.getScheme());
123 bool found = false;
124 for(proto=curl_info->protocols; !found && *proto; ++proto)
125 {
126 if( scheme == std::string((const char *)*proto))
127 found = true;
128 }
129 if( !found)
130 {
131 std::string msg("Unsupported protocol '");
132 msg += scheme;
133 msg += "'";
135 }
136 }
137}
138
140{
141 {
143 if( _curlDebug > 0)
144 {
145 curl_easy_setopt( _curl, CURLOPT_VERBOSE, 1L);
146 curl_easy_setopt( _curl, CURLOPT_DEBUGFUNCTION, log_curl);
147 curl_easy_setopt( _curl, CURLOPT_DEBUGDATA, &_curlDebug);
148 }
149 }
150
151 curl_easy_setopt(_curl, CURLOPT_HEADERFUNCTION, log_redirects_curl);
152 curl_easy_setopt(_curl, CURLOPT_HEADERDATA, &_lastRedirect);
153 CURLcode ret = curl_easy_setopt( _curl, CURLOPT_ERRORBUFFER, _curlError );
154 if ( ret != 0 ) {
155 ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer"));
156 }
157
158 SET_OPTION(CURLOPT_FAILONERROR, 1L);
159 SET_OPTION(CURLOPT_NOSIGNAL, 1L);
160
161 // create non persistant settings
162 // so that we don't add headers twice
163 TransferSettings vol_settings(_settings);
164
165// Disable custom headers -- Arachnos
166#ifdef ANONYMOUS_ID
167 // add custom headers for download.opensuse.org (bsc#955801)
168 if ( _url.getHost() == "download.opensuse.org" )
169 {
170 vol_settings.addHeader(anonymousIdHeader());
171 vol_settings.addHeader(distributionFlavorHeader());
172 }
173#endif
174 vol_settings.addHeader("Pragma:");
175
176 _settings.setTimeout(ZConfig::instance().download_transfer_timeout());
178
180
181 // fill some settings from url query parameters
182 try
183 {
185 }
186 catch ( const MediaException &e )
187 {
189 ZYPP_RETHROW(e);
190 }
191 // if the proxy was not set (or explicitly unset) by url, then look...
192 if ( _settings.proxy().empty() )
193 {
194 // ...at the system proxy settings
196 }
197
200 {
201 case 4: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); break;
202 case 6: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); break;
203 }
204
208 SET_OPTION(CURLOPT_CONNECTTIMEOUT, _settings.connectTimeout());
209 // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit
210 // just in case curl does not trigger its progress callback frequently
211 // enough.
212 if ( _settings.timeout() )
213 {
214 SET_OPTION(CURLOPT_TIMEOUT, 3600L);
215 }
216
217 // follow any Location: header that the server sends as part of
218 // an HTTP header (#113275)
219 SET_OPTION(CURLOPT_FOLLOWLOCATION, 1L);
220 // 3 redirects seem to be too few in some cases (bnc #465532)
221 SET_OPTION(CURLOPT_MAXREDIRS, 6L);
222
223 if ( _url.getScheme() == "https" )
224 {
225#if CURLVERSION_AT_LEAST(7,19,4)
226 // restrict following of redirections from https to https only
227 if ( _url.getHost() == "download.opensuse.org" )
228 SET_OPTION( CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS );
229 else
230 SET_OPTION( CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS );
231#endif
232
235 {
237 }
238
240 {
241 SET_OPTION(CURLOPT_SSLCERT, _settings.clientCertificatePath().c_str());
242 }
243 if( ! _settings.clientKeyPath().empty() )
244 {
245 SET_OPTION(CURLOPT_SSLKEY, _settings.clientKeyPath().c_str());
246 }
247
248#ifdef CURLSSLOPT_ALLOW_BEAST
249 // see bnc#779177
250 ret = curl_easy_setopt( _curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST );
251 if ( ret != 0 ) {
254 }
255#endif
256 SET_OPTION(CURLOPT_SSL_VERIFYPEER, _settings.verifyPeerEnabled() ? 1L : 0L);
257 SET_OPTION(CURLOPT_SSL_VERIFYHOST, _settings.verifyHostEnabled() ? 2L : 0L);
258 // bnc#903405 - POODLE: libzypp should only talk TLS
259 SET_OPTION(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
260 }
261
262 SET_OPTION(CURLOPT_USERAGENT, _settings.userAgentString().c_str() );
263
264 /* Fixes bsc#1174011 "auth=basic ignored in some cases"
265 * We should proactively add the password to the request if basic auth is configured
266 * and a password is available in the credentials but not in the URL.
267 *
268 * We will be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route
269 * and ask the server first about the auth method
270 */
271 if ( _settings.authType() == "basic"
272 && _settings.username().size()
273 && !_settings.password().size() ) {
274
276 const auto cred = cm.getCred( _url );
277 if ( cred && cred->valid() ) {
278 if ( !_settings.username().size() )
279 _settings.setUsername(cred->username());
280 _settings.setPassword(cred->password());
281 }
282 }
283
284 /*---------------------------------------------------------------*
285 CURLOPT_USERPWD: [user name]:[password]
286
287 Url::username/password -> CURLOPT_USERPWD
288 If not provided, anonymous FTP identification
289 *---------------------------------------------------------------*/
290
291 if ( _settings.userPassword().size() )
292 {
293 SET_OPTION(CURLOPT_USERPWD, _settings.userPassword().c_str());
294 std::string use_auth = _settings.authType();
295 if (use_auth.empty())
296 use_auth = "digest,basic"; // our default
297 long auth = CurlAuthData::auth_type_str2long(use_auth);
298 if( auth != CURLAUTH_NONE)
299 {
300 DBG << "Enabling HTTP authentication methods: " << use_auth
301 << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl;
302 SET_OPTION(CURLOPT_HTTPAUTH, auth);
303 }
304 }
305
306 if ( _settings.proxyEnabled() && ! _settings.proxy().empty() )
307 {
308 DBG << "Proxy: '" << _settings.proxy() << "'" << endl;
309 SET_OPTION(CURLOPT_PROXY, _settings.proxy().c_str());
310 SET_OPTION(CURLOPT_PROXYAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST|CURLAUTH_NTLM );
311 /*---------------------------------------------------------------*
312 * CURLOPT_PROXYUSERPWD: [user name]:[password]
313 *
314 * Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD
315 * If not provided, $HOME/.curlrc is evaluated
316 *---------------------------------------------------------------*/
317
318 std::string proxyuserpwd = _settings.proxyUserPassword();
319
320 if ( proxyuserpwd.empty() )
321 {
322 CurlConfig curlconf;
323 CurlConfig::parseConfig(curlconf); // parse ~/.curlrc
324 if ( curlconf.proxyuserpwd.empty() )
325 DBG << "Proxy: ~/.curlrc does not contain the proxy-user option" << endl;
326 else
327 {
328 proxyuserpwd = curlconf.proxyuserpwd;
329 DBG << "Proxy: using proxy-user from ~/.curlrc" << endl;
330 }
331 }
332 else
333 {
334 DBG << "Proxy: using provided proxy-user '" << _settings.proxyUsername() << "'" << endl;
335 }
336
337 if ( ! proxyuserpwd.empty() )
338 {
339 SET_OPTION(CURLOPT_PROXYUSERPWD, curlUnEscape( proxyuserpwd ).c_str());
340 }
341 }
342#if CURLVERSION_AT_LEAST(7,19,4)
343 else if ( _settings.proxy() == EXPLICITLY_NO_PROXY )
344 {
345 // Explicitly disabled in URL (see fillSettingsFromUrl()).
346 // This should also prevent libcurl from looking into the environment.
347 DBG << "Proxy: explicitly NOPROXY" << endl;
348 SET_OPTION(CURLOPT_NOPROXY, "*");
349 }
350#endif
351 else
352 {
353 DBG << "Proxy: not explicitly set" << endl;
354 DBG << "Proxy: libcurl may look into the environment" << endl;
355 }
356
358 if ( _settings.minDownloadSpeed() != 0 )
359 {
360 SET_OPTION(CURLOPT_LOW_SPEED_LIMIT, _settings.minDownloadSpeed());
361 // default to 10 seconds at low speed
362 SET_OPTION(CURLOPT_LOW_SPEED_TIME, 60L);
363 }
364
365#if CURLVERSION_AT_LEAST(7,15,5)
366 if ( _settings.maxDownloadSpeed() != 0 )
367 SET_OPTION_OFFT(CURLOPT_MAX_RECV_SPEED_LARGE, _settings.maxDownloadSpeed());
368#endif
369
370 /*---------------------------------------------------------------*
371 *---------------------------------------------------------------*/
372
375 if ( str::strToBool( _url.getQueryParam( "cookies" ), true ) )
376 SET_OPTION(CURLOPT_COOKIEFILE, _currentCookieFile.c_str() );
377 else
378 MIL << "No cookies requested" << endl;
379 SET_OPTION(CURLOPT_COOKIEJAR, _currentCookieFile.c_str() );
380 SET_OPTION(CURLOPT_PROGRESSFUNCTION, &progressCallback );
381 SET_OPTION(CURLOPT_NOPROGRESS, 0L);
382
383#if CURLVERSION_AT_LEAST(7,18,0)
384 // bnc #306272
385 SET_OPTION(CURLOPT_PROXY_TRANSFER_MODE, 1L );
386#endif
387 // append settings custom headers to curl
388 for ( const auto &header : vol_settings.headers() )
389 {
390 // MIL << "HEADER " << *it << std::endl;
391
392 _customHeaders = curl_slist_append(_customHeaders, header.c_str());
393 if ( !_customHeaders )
395 }
396
397 SET_OPTION(CURLOPT_HTTPHEADER, _customHeaders);
398}
399
401
402
403void MediaCurl::attachTo (bool next)
404{
405 if ( next )
407
408 if ( !_url.isValid() )
410
413 {
415 }
416
417 disconnectFrom(); // clean _curl if needed
418 _curl = curl_easy_init();
419 if ( !_curl ) {
421 }
422 try
423 {
424 setupEasy();
425 }
426 catch (Exception & ex)
427 {
429 ZYPP_RETHROW(ex);
430 }
431
432 // FIXME: need a derived class to propelly compare url's
434 setMediaSource(media);
435}
436
437bool
439{
440 return MediaHandler::checkAttachPoint( apoint, true, true);
441}
442
444
446{
447 if ( _customHeaders )
448 {
449 curl_slist_free_all(_customHeaders);
450 _customHeaders = 0L;
451 }
452
453 if ( _curl )
454 {
455 curl_easy_cleanup( _curl );
456 _curl = NULL;
457 }
458}
459
461
462void MediaCurl::releaseFrom( const std::string & ejectDev )
463{
464 disconnect();
465}
466
467Url MediaCurl::getFileUrl( const Pathname & filename_r ) const
468{
469 // Simply extend the URLs pathname. An 'absolute' URL path
470 // is achieved by encoding the leading '/' in an URL path:
471 // URL: ftp://user@server -> ~user
472 // URL: ftp://user@server/ -> ~user
473 // URL: ftp://user@server// -> ~user
474 // URL: ftp://user@server/%2F -> /
475 // ^- this '/' is just a separator
476 Url newurl( _url );
477 newurl.setPathName( ( Pathname("./"+_url.getPathName()) / filename_r ).asString().substr(1) );
478 return newurl;
479}
480
482
483void MediaCurl::getFile( const OnMediaLocation &file ) const
484{
485 // Use absolute file name to prevent access of files outside of the
486 // hierarchy below the attach point.
487 getFileCopy( file, localPath(file.filename()).absolutename() );
488}
489
491
492void MediaCurl::getFileCopy( const OnMediaLocation & srcFile , const Pathname & target ) const
493{
494
495 const auto &filename = srcFile.filename();
496
498
499 Url fileurl(getFileUrl(filename));
500
501 bool retry = false;
502
503 do
504 {
505 try
506 {
507 doGetFileCopy( srcFile, target, report );
508 retry = false;
509 }
510 // retry with proper authentication data
511 catch (MediaUnauthorizedException & ex_r)
512 {
513 if(authenticate(ex_r.hint(), !retry))
514 retry = true;
515 else
516 {
518 ZYPP_RETHROW(ex_r);
519 }
520 }
521 // unexpected exception
522 catch (MediaException & excpt_r)
523 {
525 if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) ||
526 typeid(excpt_r) == typeid( media::MediaNotAFileException ) )
527 {
529 }
530 report->finish(fileurl, reason, excpt_r.asUserHistory());
531 ZYPP_RETHROW(excpt_r);
532 }
533 }
534 while (retry);
535
536 report->finish(fileurl, zypp::media::DownloadProgressReport::NO_ERROR, "");
537}
538
540
541bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
542{
543 bool retry = false;
544
545 do
546 {
547 try
548 {
549 return doGetDoesFileExist( filename );
550 }
551 // authentication problem, retry with proper authentication data
552 catch (MediaUnauthorizedException & ex_r)
553 {
554 if(authenticate(ex_r.hint(), !retry))
555 retry = true;
556 else
557 ZYPP_RETHROW(ex_r);
558 }
559 // unexpected exception
560 catch (MediaException & excpt_r)
561 {
562 ZYPP_RETHROW(excpt_r);
563 }
564 }
565 while (retry);
566
567 return false;
568}
569
571
573 CURLcode code,
574 bool timeout_reached) const
575{
576 if ( code != 0 )
577 {
578 Url url;
579 if (filename.empty())
580 url = _url;
581 else
582 url = getFileUrl(filename);
583
584 std::string err;
585 {
586 switch ( code )
587 {
588 case CURLE_UNSUPPORTED_PROTOCOL:
589 err = " Unsupported protocol";
590 if ( !_lastRedirect.empty() )
591 {
592 err += " or redirect (";
593 err += _lastRedirect;
594 err += ")";
595 }
596 break;
597 case CURLE_URL_MALFORMAT:
598 case CURLE_URL_MALFORMAT_USER:
599 err = " Bad URL";
600 break;
601 case CURLE_LOGIN_DENIED:
603 MediaUnauthorizedException(url, "Login failed.", _curlError, ""));
604 break;
605 case CURLE_HTTP_RETURNED_ERROR:
606 {
607 long httpReturnCode = 0;
608 CURLcode infoRet = curl_easy_getinfo( _curl,
609 CURLINFO_RESPONSE_CODE,
610 &httpReturnCode );
611 if ( infoRet == CURLE_OK )
612 {
613 std::string msg = "HTTP response: " + str::numstring( httpReturnCode );
614 switch ( httpReturnCode )
615 {
616 case 401:
617 {
618 std::string auth_hint = getAuthHint();
619
620 DBG << msg << " Login failed (URL: " << url.asString() << ")" << std::endl;
621 DBG << "MediaUnauthorizedException auth hint: '" << auth_hint << "'" << std::endl;
622
624 url, "Login failed.", _curlError, auth_hint
625 ));
626 }
627
628 case 502: // bad gateway (bnc #1070851)
629 case 503: // service temporarily unavailable (bnc #462545)
631 case 504: // gateway timeout
633 case 403:
634 {
635 std::string msg403;
636 if ( url.getHost().find(".suse.com") != std::string::npos )
637 msg403 = _("Visit the SUSE Customer Center to check whether your registration is valid and has not expired.");
638 else if (url.asString().find("novell.com") != std::string::npos)
639 msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired.");
641 }
642 case 404:
643 case 410:
645 }
646
647 DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
649 }
650 else
651 {
652 std::string msg = "Unable to retrieve HTTP response:";
653 DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
655 }
656 }
657 break;
658 case CURLE_FTP_COULDNT_RETR_FILE:
659#if CURLVERSION_AT_LEAST(7,16,0)
660 case CURLE_REMOTE_FILE_NOT_FOUND:
661#endif
662 case CURLE_FTP_ACCESS_DENIED:
663 case CURLE_TFTP_NOTFOUND:
664 err = "File not found";
666 break;
667 case CURLE_BAD_PASSWORD_ENTERED:
668 case CURLE_FTP_USER_PASSWORD_INCORRECT:
669 err = "Login failed";
670 break;
671 case CURLE_COULDNT_RESOLVE_PROXY:
672 case CURLE_COULDNT_RESOLVE_HOST:
673 case CURLE_COULDNT_CONNECT:
674 case CURLE_FTP_CANT_GET_HOST:
675 err = "Connection failed";
676 break;
677 case CURLE_WRITE_ERROR:
678 err = "Write error";
679 break;
680 case CURLE_PARTIAL_FILE:
681 case CURLE_OPERATION_TIMEDOUT:
682 timeout_reached = true; // fall though to TimeoutException
683 // fall though...
684 case CURLE_ABORTED_BY_CALLBACK:
685 if( timeout_reached )
686 {
687 err = "Timeout reached";
689 }
690 else
691 {
692 err = "User abort";
693 }
694 break;
695 case CURLE_SSL_PEER_CERTIFICATE:
696 default:
697 err = "Curl error " + str::numstring( code );
698 break;
699 }
700
701 // uhm, no 0 code but unknown curl exception
703 }
704 }
705 else
706 {
707 // actually the code is 0, nothing happened
708 }
709}
710
712
713bool MediaCurl::doGetDoesFileExist( const Pathname & filename ) const
714{
715 DBG << filename.asString() << endl;
716
717 if(!_url.isValid())
719
720 if(_url.getHost().empty())
722
723 Url url(getFileUrl(filename));
724
725 DBG << "URL: " << url.asString() << endl;
726 // Use URL without options and without username and passwd
727 // (some proxies dislike them in the URL).
728 // Curl seems to need the just scheme, hostname and a path;
729 // the rest was already passed as curl options (in attachTo).
730 Url curlUrl( clearQueryString(url) );
731
732 //
733 // See also Bug #154197 and ftp url definition in RFC 1738:
734 // The url "ftp://user@host/foo/bar/file" contains a path,
735 // that is relative to the user's home.
736 // The url "ftp://user@host//foo/bar/file" (or also with
737 // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
738 // contains an absolute path.
739 //
740 _lastRedirect.clear();
741 std::string urlBuffer( curlUrl.asString());
742 CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
743 urlBuffer.c_str() );
744 if ( ret != 0 ) {
746 }
747
748 // instead of returning no data with NOBODY, we return
749 // little data, that works with broken servers, and
750 // works for ftp as well, because retrieving only headers
751 // ftp will return always OK code ?
752 // See http://curl.haxx.se/docs/knownbugs.html #58
753 if ( (_url.getScheme() == "http" || _url.getScheme() == "https") &&
755 ret = curl_easy_setopt( _curl, CURLOPT_NOBODY, 1L );
756 else
757 ret = curl_easy_setopt( _curl, CURLOPT_RANGE, "0-1" );
758
759 if ( ret != 0 ) {
760 curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
761 curl_easy_setopt( _curl, CURLOPT_RANGE, NULL );
762 /* yes, this is why we never got to get NOBODY working before,
763 because setting it changes this option too, and we also
764 need to reset it
765 See: http://curl.haxx.se/mail/archive-2005-07/0073.html
766 */
767 curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
769 }
770
771 AutoFILE file { ::fopen( "/dev/null", "w" ) };
772 if ( !file ) {
773 ERR << "fopen failed for /dev/null" << endl;
774 curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
775 curl_easy_setopt( _curl, CURLOPT_RANGE, NULL );
776 /* yes, this is why we never got to get NOBODY working before,
777 because setting it changes this option too, and we also
778 need to reset it
779 See: http://curl.haxx.se/mail/archive-2005-07/0073.html
780 */
781 curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
782 if ( ret != 0 ) {
784 }
785 ZYPP_THROW(MediaWriteException("/dev/null"));
786 }
787
788 ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, (*file) );
789 if ( ret != 0 ) {
790 std::string err( _curlError);
791 curl_easy_setopt( _curl, CURLOPT_RANGE, NULL );
792 curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
793 /* yes, this is why we never got to get NOBODY working before,
794 because setting it changes this option too, and we also
795 need to reset it
796 See: http://curl.haxx.se/mail/archive-2005-07/0073.html
797 */
798 curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L );
799 if ( ret != 0 ) {
801 }
803 }
804
805 CURLcode ok = curl_easy_perform( _curl );
806 MIL << "perform code: " << ok << " [ " << curl_easy_strerror(ok) << " ]" << endl;
807
808 // reset curl settings
809 if ( _url.getScheme() == "http" || _url.getScheme() == "https" )
810 {
811 curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L);
812 if ( ret != 0 ) {
814 }
815
816 /* yes, this is why we never got to get NOBODY working before,
817 because setting it changes this option too, and we also
818 need to reset it
819 See: http://curl.haxx.se/mail/archive-2005-07/0073.html
820 */
821 curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L);
822 if ( ret != 0 ) {
824 }
825
826 }
827 else
828 {
829 // for FTP we set different options
830 curl_easy_setopt( _curl, CURLOPT_RANGE, NULL);
831 if ( ret != 0 ) {
833 }
834 }
835
836 // as we are not having user interaction, the user can't cancel
837 // the file existence checking, a callback or timeout return code
838 // will be always a timeout.
839 try {
840 evaluateCurlCode( filename, ok, true /* timeout */);
841 }
842 catch ( const MediaFileNotFoundException &e ) {
843 // if the file did not exist then we can return false
844 return false;
845 }
846 catch ( const MediaException &e ) {
847 // some error, we are not sure about file existence, rethrw
848 ZYPP_RETHROW(e);
849 }
850 // exists
851 return ( ok == CURLE_OK );
852}
853
855
856
857#if DETECT_DIR_INDEX
858bool MediaCurl::detectDirIndex() const
859{
860 if(_url.getScheme() != "http" && _url.getScheme() != "https")
861 return false;
862 //
863 // try to check the effective url and set the not_a_file flag
864 // if the url path ends with a "/", what usually means, that
865 // we've received a directory index (index.html content).
866 //
867 // Note: This may be dangerous and break file retrieving in
868 // case of some server redirections ... ?
869 //
870 bool not_a_file = false;
871 char *ptr = NULL;
872 CURLcode ret = curl_easy_getinfo( _curl,
873 CURLINFO_EFFECTIVE_URL,
874 &ptr);
875 if ( ret == CURLE_OK && ptr != NULL)
876 {
877 try
878 {
879 Url eurl( ptr);
880 std::string path( eurl.getPathName());
881 if( !path.empty() && path != "/" && *path.rbegin() == '/')
882 {
883 DBG << "Effective url ("
884 << eurl
885 << ") seems to provide the index of a directory"
886 << endl;
887 not_a_file = true;
888 }
889 }
890 catch( ... )
891 {}
892 }
893 return not_a_file;
894}
895#endif
896
898
899void MediaCurl::doGetFileCopy( const OnMediaLocation &srcFile , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
900{
901 Pathname dest = target.absolutename();
902 if( assert_dir( dest.dirname() ) )
903 {
904 DBG << "assert_dir " << dest.dirname() << " failed" << endl;
905 ZYPP_THROW( MediaSystemException(getFileUrl(srcFile.filename()), "System error on " + dest.dirname().asString()) );
906 }
907
908 ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) };
909 AutoFILE file;
910 {
911 AutoFREE<char> buf { ::strdup( (*destNew).c_str() ) };
912 if( ! buf )
913 {
914 ERR << "out of memory for temp file name" << endl;
915 ZYPP_THROW(MediaSystemException(getFileUrl(srcFile.filename()), "out of memory for temp file name"));
916 }
917
918 AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
919 if( tmp_fd == -1 )
920 {
921 ERR << "mkstemp failed for file '" << destNew << "'" << endl;
923 }
924 destNew = ManagedFile( (*buf), filesystem::unlink );
925
926 file = ::fdopen( tmp_fd, "we" );
927 if ( ! file )
928 {
929 ERR << "fopen failed for file '" << destNew << "'" << endl;
931 }
932 tmp_fd.resetDispose(); // don't close it here! ::fdopen moved ownership to file
933 }
934
935 DBG << "dest: " << dest << endl;
936 DBG << "temp: " << destNew << endl;
937
938 // set IFMODSINCE time condition (no download if not modified)
939 if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) )
940 {
941 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
942 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime());
943 }
944 else
945 {
946 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
947 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
948 }
949 try
950 {
951 doGetFileCopyFile( srcFile, dest, file, report, options);
952 }
953 catch (Exception &e)
954 {
955 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
956 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
957 ZYPP_RETHROW(e);
958 }
959
960 long httpReturnCode = 0;
961 CURLcode infoRet = curl_easy_getinfo(_curl,
962 CURLINFO_RESPONSE_CODE,
963 &httpReturnCode);
964 bool modified = true;
965 if (infoRet == CURLE_OK)
966 {
967 DBG << "HTTP response: " + str::numstring(httpReturnCode);
968 if ( httpReturnCode == 304
969 || ( httpReturnCode == 213 && (_url.getScheme() == "ftp" || _url.getScheme() == "tftp") ) ) // not modified
970 {
971 DBG << " Not modified.";
972 modified = false;
973 }
974 DBG << endl;
975 }
976 else
977 {
978 WAR << "Could not get the reponse code." << endl;
979 }
980
981 if (modified || infoRet != CURLE_OK)
982 {
983 // apply umask
984 if ( ::fchmod( ::fileno(file), filesystem::applyUmaskTo( 0644 ) ) )
985 {
986 ERR << "Failed to chmod file " << destNew << endl;
987 }
988
989 file.resetDispose(); // we're going to close it manually here
990 if ( ::fclose( file ) )
991 {
992 ERR << "Fclose failed for file '" << destNew << "'" << endl;
994 }
995
996 // move the temp file into dest
997 if ( rename( destNew, dest ) != 0 ) {
998 ERR << "Rename failed" << endl;
1000 }
1001 destNew.resetDispose(); // no more need to unlink it
1002 }
1003
1004 DBG << "done: " << PathInfo(dest) << endl;
1005}
1006
1008
1009void MediaCurl::doGetFileCopyFile( const OnMediaLocation & srcFile, const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
1010{
1011 DBG << srcFile.filename().asString() << endl;
1012
1013 if(!_url.isValid())
1015
1016 if(_url.getHost().empty())
1018
1019 Url url(getFileUrl(srcFile.filename()));
1020
1021 DBG << "URL: " << url.asString() << endl;
1022 // Use URL without options and without username and passwd
1023 // (some proxies dislike them in the URL).
1024 // Curl seems to need the just scheme, hostname and a path;
1025 // the rest was already passed as curl options (in attachTo).
1026 Url curlUrl( clearQueryString(url) );
1027
1028 //
1029 // See also Bug #154197 and ftp url definition in RFC 1738:
1030 // The url "ftp://user@host/foo/bar/file" contains a path,
1031 // that is relative to the user's home.
1032 // The url "ftp://user@host//foo/bar/file" (or also with
1033 // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
1034 // contains an absolute path.
1035 //
1036 _lastRedirect.clear();
1037 std::string urlBuffer( curlUrl.asString());
1038 CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
1039 urlBuffer.c_str() );
1040 if ( ret != 0 ) {
1042 }
1043
1044 ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, file );
1045 if ( ret != 0 ) {
1047 }
1048
1049 // Set callback and perform.
1050 internal::ProgressData progressData(_curl, _settings.timeout(), url, srcFile.downloadSize(), &report);
1051 if (!(options & OPTION_NO_REPORT_START))
1052 report->start(url, dest);
1053 if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) {
1054 WAR << "Can't set CURLOPT_PROGRESSDATA: " << _curlError << endl;;
1055 }
1056
1057 ret = curl_easy_perform( _curl );
1058#if CURLVERSION_AT_LEAST(7,19,4)
1059 // bnc#692260: If the client sends a request with an If-Modified-Since header
1060 // with a future date for the server, the server may respond 200 sending a
1061 // zero size file.
1062 // curl-7.19.4 introduces CURLINFO_CONDITION_UNMET to check this condition.
1063 if ( ftell(file) == 0 && ret == 0 )
1064 {
1065 long httpReturnCode = 33;
1066 if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 )
1067 {
1068 long conditionUnmet = 33;
1069 if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet )
1070 {
1071 WAR << "TIMECONDITION unmet - retry without." << endl;
1072 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1073 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
1074 ret = curl_easy_perform( _curl );
1075 }
1076 }
1077 }
1078#endif
1079
1080 if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, NULL ) != 0 ) {
1081 WAR << "Can't unset CURLOPT_PROGRESSDATA: " << _curlError << endl;;
1082 }
1083
1084 if ( ret != 0 )
1085 {
1086 ERR << "curl error: " << ret << ": " << _curlError
1087 << ", temp file size " << ftell(file)
1088 << " bytes." << endl;
1089
1090 // the timeout is determined by the progress data object
1091 // which holds whether the timeout was reached or not,
1092 // otherwise it would be a user cancel
1093 try {
1094
1095 if ( progressData.fileSizeExceeded )
1097
1098 evaluateCurlCode( srcFile.filename(), ret, progressData.reached );
1099 }
1100 catch ( const MediaException &e ) {
1101 // some error, we are not sure about file existence, rethrw
1102 ZYPP_RETHROW(e);
1103 }
1104 }
1105
1106#if DETECT_DIR_INDEX
1107 if (!ret && detectDirIndex())
1108 {
1110 }
1111#endif // DETECT_DIR_INDEX
1112}
1113
1115
1116void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const
1117{
1118 filesystem::DirContent content;
1119 getDirInfo( content, dirname, /*dots*/false );
1120
1121 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1122 Pathname filename = dirname + it->name;
1123 int res = 0;
1124
1125 switch ( it->type ) {
1126 case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
1128 getFile( OnMediaLocation( filename ) );
1129 break;
1130 case filesystem::FT_DIR: // newer directory.yast contain at least directory info
1131 if ( recurse_r ) {
1132 getDir( filename, recurse_r );
1133 } else {
1134 res = assert_dir( localPath( filename ) );
1135 if ( res ) {
1136 WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl;
1137 }
1138 }
1139 break;
1140 default:
1141 // don't provide devices, sockets, etc.
1142 break;
1143 }
1144 }
1145}
1146
1148
1149void MediaCurl::getDirInfo( std::list<std::string> & retlist,
1150 const Pathname & dirname, bool dots ) const
1151{
1152 getDirectoryYast( retlist, dirname, dots );
1153}
1154
1156
1158 const Pathname & dirname, bool dots ) const
1159{
1160 getDirectoryYast( retlist, dirname, dots );
1161}
1162
1164//
1165int MediaCurl::aliveCallback( void *clientp, double /*dltotal*/, double dlnow, double /*ultotal*/, double /*ulnow*/ )
1166{
1167 internal::ProgressData *pdata = reinterpret_cast<internal::ProgressData *>( clientp );
1168 if( pdata )
1169 {
1170 // Do not propagate dltotal in alive callbacks. MultiCurl uses this to
1171 // prevent a percentage raise while downloading a metalink file. Download
1172 // activity however is indicated by propagating the download rate (via dlnow).
1173 pdata->updateStats( 0.0, dlnow );
1174 return pdata->reportProgress();
1175 }
1176 return 0;
1177}
1178
1179int MediaCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
1180{
1181 internal::ProgressData *pdata = reinterpret_cast<internal::ProgressData *>( clientp );
1182 if( pdata )
1183 {
1184 // work around curl bug that gives us old data
1185 long httpReturnCode = 0;
1186 if ( curl_easy_getinfo( pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0 )
1187 return aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow );
1188
1189 pdata->updateStats( dltotal, dlnow );
1190 return pdata->reportProgress();
1191 }
1192 return 0;
1193}
1194
1196{
1197 internal::ProgressData *pdata = reinterpret_cast<internal::ProgressData *>(clientp);
1198 return pdata ? pdata->curl : 0;
1199}
1200
1202
1203std::string MediaCurl::getAuthHint() const
1204{
1205 long auth_info = CURLAUTH_NONE;
1206
1207 CURLcode infoRet =
1208 curl_easy_getinfo(_curl, CURLINFO_HTTPAUTH_AVAIL, &auth_info);
1209
1210 if(infoRet == CURLE_OK)
1211 {
1212 return CurlAuthData::auth_type_long2str(auth_info);
1213 }
1214
1215 return "";
1216}
1217
1222void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
1223{
1224 internal::ProgressData *data = reinterpret_cast<internal::ProgressData *>(clientp);
1225 if ( data ) {
1226 data->_expectedFileSize = expectedFileSize;
1227 }
1228}
1229
1231
1232bool MediaCurl::authenticate(const std::string & availAuthTypes, bool firstTry) const
1233{
1236 CurlAuthData_Ptr credentials;
1237
1238 // get stored credentials
1239 AuthData_Ptr cmcred = cm.getCred(_url);
1240
1241 if (cmcred && firstTry)
1242 {
1243 credentials.reset(new CurlAuthData(*cmcred));
1244 DBG << "got stored credentials:" << endl << *credentials << endl;
1245 }
1246 // if not found, ask user
1247 else
1248 {
1249
1250 CurlAuthData_Ptr curlcred;
1251 curlcred.reset(new CurlAuthData());
1253
1254 // preset the username if present in current url
1255 if (!_url.getUsername().empty() && firstTry)
1256 curlcred->setUsername(_url.getUsername());
1257 // if CM has found some credentials, preset the username from there
1258 else if (cmcred)
1259 curlcred->setUsername(cmcred->username());
1260
1261 // indicate we have no good credentials from CM
1262 cmcred.reset();
1263
1264 std::string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString();
1265
1266 // set available authentication types from the exception
1267 // might be needed in prompt
1268 curlcred->setAuthType(availAuthTypes);
1269
1270 // ask user
1271 if (auth_report->prompt(_url, prompt_msg, *curlcred))
1272 {
1273 DBG << "callback answer: retry" << endl
1274 << "CurlAuthData: " << *curlcred << endl;
1275
1276 if (curlcred->valid())
1277 {
1278 credentials = curlcred;
1279 // if (credentials->username() != _url.getUsername())
1280 // _url.setUsername(credentials->username());
1288 }
1289 }
1290 else
1291 {
1292 DBG << "callback answer: cancel" << endl;
1293 }
1294 }
1295
1296 // set username and password
1297 if (credentials)
1298 {
1299 // HACK, why is this const?
1300 const_cast<MediaCurl*>(this)->_settings.setUsername(credentials->username());
1301 const_cast<MediaCurl*>(this)->_settings.setPassword(credentials->password());
1302
1303 // set username and password
1304 CURLcode ret = curl_easy_setopt(_curl, CURLOPT_USERPWD, _settings.userPassword().c_str());
1306
1307 // set available authentication types from the exception
1308 if (credentials->authType() == CURLAUTH_NONE)
1309 credentials->setAuthType(availAuthTypes);
1310
1311 // set auth type (seems this must be set _after_ setting the userpwd)
1312 if (credentials->authType() != CURLAUTH_NONE)
1313 {
1314 // FIXME: only overwrite if not empty?
1315 const_cast<MediaCurl*>(this)->_settings.setAuthType(credentials->authTypeAsString());
1316 ret = curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, credentials->authType());
1318 }
1319
1320 if (!cmcred)
1321 {
1322 credentials->setUrl(_url);
1323 cm.addCred(*credentials);
1324 cm.save();
1325 }
1326
1327 return true;
1328 }
1329
1330 return false;
1331}
1332
1333//need a out of line definiton, otherwise vtable is emitted for every translation unit
1335
1336 } // namespace media
1337} // namespace zypp
1338//
#define CONNECT_TIMEOUT
Definition: CurlHelper.h:22
#define EXPLICITLY_NO_PROXY
Definition: CurlHelper.h:26
#define SET_OPTION_OFFT(opt, val)
Definition: MediaCurl.cc:62
#define SET_OPTION(opt, val)
Definition: MediaCurl.cc:55
Convenience interface for handling authentication data of media user.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:94
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:164
Store and operate with byte count.
Definition: ByteCount.h:31
Base class for Exception.
Definition: Exception.h:146
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:91
Describes a resource file located on a medium.
const ByteCount & downloadSize() const
The size of the resource on the server.
const Pathname & filename() const
The path to the resource on the medium.
Url manipulation class.
Definition: Url.h:92
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:533
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:497
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
Definition: Url.cc:572
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:604
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:660
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:764
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition: Url.cc:588
bool isValid() const
Verifies the Url.
Definition: Url.cc:489
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
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:170
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
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
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:82
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:31
virtual void setupEasy()
initializes the curl easy handle with the data from the url
Definition: MediaCurl.cc:139
Url getFileUrl(const Pathname &filename) const
concatenate the attach url and the filename to a complete download url
Definition: MediaCurl.cc:467
static void setCookieFile(const Pathname &)
Definition: MediaCurl.cc:107
virtual bool getDoesFileExist(const Pathname &filename) const override
Repeatedly calls doGetDoesFileExist() until it successfully returns, fails unexpectedly,...
Definition: MediaCurl.cc:541
@ OPTION_NO_IFMODSINCE
to not add a IFMODSINCE header if target exists
Definition: MediaCurl.h:42
@ OPTION_NO_REPORT_START
do not send a start ProgressReport
Definition: MediaCurl.h:44
virtual void getFile(const OnMediaLocation &file) const override
Call concrete handler to provide file below attach point.
Definition: MediaCurl.cc:483
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:1222
std::string _currentCookieFile
Definition: MediaCurl.h:166
static int aliveCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
Definition: MediaCurl.cc:1165
static Pathname _cookieFile
Definition: MediaCurl.h:167
static int progressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
Callback reporting download progress.
Definition: MediaCurl.cc:1179
virtual void getFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename) const override
Definition: MediaCurl.cc:492
virtual void doGetFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename, callback::SendReport< DownloadProgressReport > &_report, RequestOptions options=OPTION_NONE) const
Definition: MediaCurl.cc:899
std::string _lastRedirect
to log/report redirections
Definition: MediaCurl.h:169
Url clearQueryString(const Url &url) const
Definition: MediaCurl.cc:102
virtual void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition: MediaCurl.cc:403
virtual 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: MediaCurl.cc:1149
char _curlError[CURL_ERROR_SIZE]
Definition: MediaCurl.h:173
void doGetFileCopyFile(const OnMediaLocation &srcFile, const Pathname &dest, FILE *file, callback::SendReport< DownloadProgressReport > &report, RequestOptions options=OPTION_NONE) const
Definition: MediaCurl.cc:1009
void checkProtocol(const Url &url) const
check the url is supported by the curl library
Definition: MediaCurl.cc:114
MediaCurl(const Url &url_r, const Pathname &attach_point_hint_r)
Definition: MediaCurl.cc:66
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:572
virtual 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:438
virtual void getDir(const Pathname &dirname, bool recurse_r) const override
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition: MediaCurl.cc:1116
bool authenticate(const std::string &availAuthTypes, bool firstTry) const
Definition: MediaCurl.cc:1232
static CURL * progressCallback_getcurl(void *clientp)
Definition: MediaCurl.cc:1195
virtual void releaseFrom(const std::string &ejectDev) override
Call concrete handler to release the media.
Definition: MediaCurl.cc:462
virtual void disconnectFrom() override
Definition: MediaCurl.cc:445
virtual bool doGetDoesFileExist(const Pathname &filename) const
Definition: MediaCurl.cc:713
curl_slist * _customHeaders
Definition: MediaCurl.h:174
std::string getAuthHint() const
Return a comma separated list of available authentication methods supported by server.
Definition: MediaCurl.cc:1203
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.
Definition: MediaHandler.h:503
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:113
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.
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:37
const std::string & hint() const
comma separated list of available authentication types
Holds transfer setting.
std::string proxy() const
proxy host
long maxDownloadSpeed() const
Maximum download speed (bytes per second)
long connectTimeout() const
connection timeout
std::string password() const
auth password
long timeout() const
transfer timeout
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 setAuthType(std::string &&val_r)
set the allowed authentication types
void setUsername(std::string &&val_r)
sets the auth username
void setUserAgentString(std::string &&val_r)
sets the user agent ie: "Mozilla v3"
void setConnectTimeout(long t)
set the connect timeout
std::string userAgentString() const
user agent string
void setPassword(std::string &&val_r)
sets the auth password
void addHeader(std::string &&val_r)
add a header, on the form "Foo: Bar"
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
bool proxyEnabled() const
proxy is enabled
std::string username() const
auth username
Headers headers() const
returns a list of all added headers
Pathname clientKeyPath() const
SSL client key file.
void setTimeout(long t)
set the transfer timeout
bool verifyPeerEnabled() const
Whether to verify peer for ssl.
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:129
size_t log_redirects_curl(char *ptr, size_t size, size_t nmemb, void *userdata)
Definition: CurlHelper.cc:89
void globalInitCurlOnce()
Definition: CurlHelper.cc:46
std::string curlUnEscape(std::string text_r)
Definition: CurlHelper.cc:360
const char * agentString()
initialized only once, this gets the agent string which also includes the curl version
Definition: CurlHelper.cc:331
void fillSettingsSystemProxy(const Url &url, media::TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Definition: CurlHelper.cc:277
Url clearQueryString(const Url &url)
Definition: CurlHelper.cc:367
int log_curl(CURL *curl, curl_infotype info, char *ptr, size_t len, void *max_lvl)
Definition: CurlHelper.cc:55
int ZYPP_MEDIA_CURL_IPRESOLVE()
4/6 to force IPv4/v6
Definition: CurlHelper.cc:35
long ZYPP_MEDIA_CURL_DEBUG()
Long number for setting CURLOPT_DEBUGDATA.
Definition: CurlHelper.h:36
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:700
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
Definition: PathInfo.cc:742
int rmdir(const Pathname &path)
Like 'rmdir'.
Definition: PathInfo.cc:366
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:319
int assert_file_mode(const Pathname &path, unsigned mode)
Like assert_file but enforce mode even if the file already exists.
Definition: PathInfo.cc:1202
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:518
shared_ptr< CurlAuthData > CurlAuthData_Ptr
shared_ptr< AuthData > AuthData_Ptr
Definition: MediaUserAuth.h:77
std::string numstring(char n, int w=0)
Definition: String.h:289
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition: String.h:429
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
zypp::ByteCount _expectedFileSize
Definition: CurlHelper.h:64
void updateStats(double dltotal=0.0, double dlnow=0.0)
Definition: CurlHelper.cc:414
int reportProgress() const
Definition: CurlHelper.cc:463
AutoDispose<int> calling ::close
Definition: AutoDispose.h:283
AutoDispose<FILE*> calling ::fclose
Definition: AutoDispose.h:294
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:253
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:400
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
#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