#include "zypp/thread/Once.h"
#include "zypp/Target.h"
#include "zypp/ZYppFactory.h"
+#include "zypp/ZConfig.h"
#include <cstdlib>
#include <sys/types.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
-#include <boost/format.hpp>
#define DETECT_DIR_INDEX 0
#define CONNECT_TIMEOUT 60
-#define TRANSFER_TIMEOUT 60 * 3
#define TRANSFER_TIMEOUT_MAX 60 * 60
#define EXPLICITLY_NO_PROXY "_none_"
return 0;
}
- static size_t
- log_redirects_curl(
- void *ptr, size_t size, size_t nmemb, void *stream)
+ static size_t log_redirects_curl( char *ptr, size_t size, size_t nmemb, void *userdata)
{
- // INT << "got header: " << string((char *)ptr, ((char*)ptr) + size*nmemb) << endl;
+ // INT << "got header: " << string(ptr, ptr + size*nmemb) << endl;
- char * lstart = (char *)ptr, * lend = (char *)ptr;
+ char * lstart = ptr, * lend = ptr;
size_t pos = 0;
size_t max = size * nmemb;
while (pos + 1 < max)
for (lstart = lend; *lend != '\n' && pos < max; ++lend, ++pos);
// look for "Location"
- string line(lstart, lend);
- if (line.find("Location") != string::npos)
+ if ( lstart[0] == 'L'
+ && lstart[1] == 'o'
+ && lstart[2] == 'c'
+ && lstart[3] == 'a'
+ && lstart[4] == 't'
+ && lstart[5] == 'i'
+ && lstart[6] == 'o'
+ && lstart[7] == 'n'
+ && lstart[8] == ':' )
{
+ std::string line { lstart, *(lend-1)=='\r' ? lend-1 : lend };
DBG << "redirecting to " << line << endl;
+ if ( userdata ) {
+ *reinterpret_cast<std::string *>( userdata ) = line;
+ }
return max;
}
}
namespace zypp {
+
+ ///////////////////////////////////////////////////////////////////
+ namespace env
+ {
+ namespace
+ {
+ inline int getZYPP_MEDIA_CURL_IPRESOLVE()
+ {
+ int ret = 0;
+ if ( const char * envp = getenv( "ZYPP_MEDIA_CURL_IPRESOLVE" ) )
+ {
+ WAR << "env set: $ZYPP_MEDIA_CURL_IPRESOLVE='" << envp << "'" << endl;
+ if ( strcmp( envp, "4" ) == 0 ) ret = 4;
+ else if ( strcmp( envp, "6" ) == 0 ) ret = 6;
+ }
+ return ret;
+ }
+ }
+
+ inline int ZYPP_MEDIA_CURL_IPRESOLVE()
+ {
+ static int _v = getZYPP_MEDIA_CURL_IPRESOLVE();
+ return _v;
+ }
+ } // namespace env
+ ///////////////////////////////////////////////////////////////////
+
namespace media {
namespace {
struct ProgressData
{
- ProgressData(CURL *_curl, const long _timeout, const zypp::Url &_url = zypp::Url(),
- callback::SendReport<DownloadProgressReport> *_report=NULL)
- : curl(_curl)
- , timeout(_timeout)
- , reached(false)
- , report(_report)
- , drate_period(-1)
- , dload_period(0)
- , secs(0)
- , drate_avg(-1)
- , ltime( time(NULL))
- , dload( 0)
- , uload( 0)
- , url(_url)
+ ProgressData( CURL *_curl, time_t _timeout = 0, const Url & _url = Url(),
+ ByteCount expectedFileSize_r = 0,
+ callback::SendReport<DownloadProgressReport> *_report = nullptr )
+ : curl( _curl )
+ , url( _url )
+ , timeout( _timeout )
+ , reached( false )
+ , fileSizeExceeded ( false )
+ , report( _report )
+ , _expectedFileSize( expectedFileSize_r )
{}
- CURL *curl;
- long timeout;
- bool reached;
+
+ CURL *curl;
+ Url url;
+ time_t timeout;
+ bool reached;
+ bool fileSizeExceeded;
callback::SendReport<DownloadProgressReport> *report;
+ ByteCount _expectedFileSize;
+
+ time_t _timeStart = 0; ///< Start total stats
+ time_t _timeLast = 0; ///< Start last period(~1sec)
+ time_t _timeRcv = 0; ///< Start of no-data timeout
+ time_t _timeNow = 0; ///< Now
+
+ double _dnlTotal = 0.0; ///< Bytes to download or 0 if unknown
+ double _dnlLast = 0.0; ///< Bytes downloaded at period start
+ double _dnlNow = 0.0; ///< Bytes downloaded now
+
+ int _dnlPercent= 0; ///< Percent completed or 0 if _dnlTotal is unknown
+
+ double _drateTotal= 0.0; ///< Download rate so far
+ double _drateLast = 0.0; ///< Download rate in last period
+
+ void updateStats( double dltotal = 0.0, double dlnow = 0.0 )
+ {
+ time_t now = _timeNow = time(0);
+
+ // If called without args (0.0), recompute based on the last values seen
+ if ( dltotal && dltotal != _dnlTotal )
+ _dnlTotal = dltotal;
+
+ if ( dlnow && dlnow != _dnlNow )
+ {
+ _timeRcv = now;
+ _dnlNow = dlnow;
+ }
+ else if ( !_dnlNow && !_dnlTotal )
+ {
+ // Start time counting as soon as first data arrives.
+ // Skip the connection / redirection time at begin.
+ return;
+ }
+
+ // init or reset if time jumps back
+ if ( !_timeStart || _timeStart > now )
+ _timeStart = _timeLast = _timeRcv = now;
+
+ // timeout condition
+ if ( timeout )
+ reached = ( (now - _timeRcv) > timeout );
+
+ // check if the downloaded data is already bigger than what we expected
+ fileSizeExceeded = _expectedFileSize > 0 && _expectedFileSize < static_cast<ByteCount::SizeType>(_dnlNow);
+
+ // percentage:
+ if ( _dnlTotal )
+ _dnlPercent = int(_dnlNow * 100 / _dnlTotal);
+
+ // download rates:
+ _drateTotal = _dnlNow / std::max( int(now - _timeStart), 1 );
+
+ if ( _timeLast < now )
+ {
+ _drateLast = (_dnlNow - _dnlLast) / int(now - _timeLast);
+ // start new period
+ _timeLast = now;
+ _dnlLast = _dnlNow;
+ }
+ else if ( _timeStart == _timeLast )
+ _drateLast = _drateTotal;
+ }
+
+ int reportProgress() const
+ {
+ if ( fileSizeExceeded )
+ return 1;
+ if ( reached )
+ return 1; // no-data timeout
+ if ( report && !(*report)->progress( _dnlPercent, url, _drateTotal, _drateLast ) )
+ return 1; // user requested abort
+ return 0;
+ }
+
+
// download rate of the last period (cca 1 sec)
double drate_period;
// bytes downloaded at the start of the last period
double dload;
// bytes uploaded at the moment the progress was last reported
double uload;
- zypp::Url url;
};
///////////////////////////////////////////////////////////////////
else
{
// if there is no username, set anonymous auth
- if ( url.getScheme() == "ftp" && s.username().empty() )
+ if ( ( url.getScheme() == "ftp" || url.getScheme() == "tftp" ) && s.username().empty() )
s.setAnonymousAuth();
}
s.setCertificateAuthoritiesPath(ca_path);
}
+ Pathname client_cert( url.getQueryParam("ssl_clientcert") );
+ if( ! client_cert.empty())
+ {
+ if( !PathInfo(client_cert).isFile() || !client_cert.absolute())
+ ZYPP_THROW(MediaBadUrlException(url, "Invalid ssl_clientcert file"));
+ else
+ s.setClientCertificatePath(client_cert);
+ }
+ Pathname client_key( url.getQueryParam("ssl_clientkey") );
+ if( ! client_key.empty())
+ {
+ if( !PathInfo(client_key).isFile() || !client_key.absolute())
+ ZYPP_THROW(MediaBadUrlException(url, "Invalid ssl_clientkey file"));
+ else
+ s.setClientKeyPath(client_key);
+ }
+
param = url.getQueryParam( "proxy" );
if ( ! param.empty() )
{
curlUrl.delQueryParam("proxypass");
curlUrl.delQueryParam("ssl_capath");
curlUrl.delQueryParam("ssl_verify");
+ curlUrl.delQueryParam("ssl_clientcert");
curlUrl.delQueryParam("timeout");
curlUrl.delQueryParam("auth");
curlUrl.delQueryParam("username");
curlUrl.delQueryParam("password");
curlUrl.delQueryParam("mediahandler");
+ curlUrl.delQueryParam("credentials");
+ curlUrl.delQueryParam("head_requests");
return curlUrl;
}
}
curl_easy_setopt(_curl, CURLOPT_HEADERFUNCTION, log_redirects_curl);
+ curl_easy_setopt(_curl, CURLOPT_HEADERDATA, &_lastRedirect);
CURLcode ret = curl_easy_setopt( _curl, CURLOPT_ERRORBUFFER, _curlError );
if ( ret != 0 ) {
ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer"));
// so that we don't add headers twice
TransferSettings vol_settings(_settings);
- // add custom headers
- vol_settings.addHeader(anonymousIdHeader());
- vol_settings.addHeader(distributionFlavorHeader());
+ // add custom headers for download.opensuse.org (bsc#955801)
+ if ( _url.getHost() == "download.opensuse.org" )
+ {
+ vol_settings.addHeader(anonymousIdHeader());
+ vol_settings.addHeader(distributionFlavorHeader());
+ }
vol_settings.addHeader("Pragma:");
- _settings.setTimeout(TRANSFER_TIMEOUT);
+ _settings.setTimeout(ZConfig::instance().download_transfer_timeout());
_settings.setConnectTimeout(CONNECT_TIMEOUT);
_settings.setUserAgentString(agentString());
fillSettingsSystemProxy(_url, _settings);
}
+ /** Force IPv4/v6 */
+ if ( env::ZYPP_MEDIA_CURL_IPRESOLVE() )
+ {
+ switch ( env::ZYPP_MEDIA_CURL_IPRESOLVE() )
+ {
+ case 4: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); break;
+ case 6: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); break;
+ }
+ }
+
/**
* Connect timeout
*/
SET_OPTION(CURLOPT_CONNECTTIMEOUT, _settings.connectTimeout());
+ // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit
+ // just in case curl does not trigger its progress callback frequently
+ // enough.
+ if ( _settings.timeout() )
+ {
+ SET_OPTION(CURLOPT_TIMEOUT, 3600L);
+ }
// follow any Location: header that the server sends as part of
// an HTTP header (#113275)
SET_OPTION(CURLOPT_CAPATH, _settings.certificateAuthoritiesPath().c_str());
}
+ if( ! _settings.clientCertificatePath().empty() )
+ {
+ SET_OPTION(CURLOPT_SSLCERT, _settings.clientCertificatePath().c_str());
+ }
+ if( ! _settings.clientKeyPath().empty() )
+ {
+ SET_OPTION(CURLOPT_SSLKEY, _settings.clientKeyPath().c_str());
+ }
+
#ifdef CURLSSLOPT_ALLOW_BEAST
// see bnc#779177
ret = curl_easy_setopt( _curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST );
#endif
SET_OPTION(CURLOPT_SSL_VERIFYPEER, _settings.verifyPeerEnabled() ? 1L : 0L);
SET_OPTION(CURLOPT_SSL_VERIFYHOST, _settings.verifyHostEnabled() ? 2L : 0L);
+ // bnc#903405 - POODLE: libzypp should only talk TLS
+ SET_OPTION(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
}
SET_OPTION(CURLOPT_USERAGENT, _settings.userAgentString().c_str() );
#endif
else
{
- // libcurl may look into the enviroanment
DBG << "Proxy: not explicitly set" << endl;
+ DBG << "Proxy: libcurl may look into the environment" << endl;
}
/** Speed limits */
{
SET_OPTION(CURLOPT_LOW_SPEED_LIMIT, _settings.minDownloadSpeed());
// default to 10 seconds at low speed
- SET_OPTION(CURLOPT_LOW_SPEED_TIME, 10L);
+ SET_OPTION(CURLOPT_LOW_SPEED_TIME, 60L);
}
#if CURLVERSION_AT_LEAST(7,15,5)
ZYPP_THROW(MediaBadUrlException(_url));
checkProtocol(_url);
- if( !isUseableAttachPoint(attachPoint()))
+ if( !isUseableAttachPoint( attachPoint() ) )
{
- std::string mountpoint = createAttachPoint().asString();
-
- if( mountpoint.empty())
- ZYPP_THROW( MediaBadAttachPointException(url()));
-
- setAttachPoint( mountpoint, true);
+ setAttachPoint( createAttachPoint(), true );
}
disconnectFrom(); // clean _curl if needed
disconnect();
}
-Url MediaCurl::getFileUrl(const Pathname & filename) const
+Url MediaCurl::getFileUrl( const Pathname & filename_r ) const
{
- Url newurl(_url);
- string path = _url.getPathName();
- if ( !path.empty() && path != "/" && *path.rbegin() == '/' &&
- filename.absolute() )
- {
- // If url has a path with trailing slash, remove the leading slash from
- // the absolute file name
- path += filename.asString().substr( 1, filename.asString().size() - 1 );
- }
- else if ( filename.relative() )
- {
- // Add trailing slash to path, if not already there
- if (path.empty()) path = "/";
- else if (*path.rbegin() != '/' ) path += "/";
- // Remove "./" from begin of relative file name
- path += filename.asString().substr( 2, filename.asString().size() - 2 );
- }
- else
- {
- path += filename.asString();
- }
-
- newurl.setPathName(path);
+ // Simply extend the URLs pathname. An 'absolute' URL path
+ // is achieved by encoding the leading '/' in an URL path:
+ // URL: ftp://user@server -> ~user
+ // URL: ftp://user@server/ -> ~user
+ // URL: ftp://user@server// -> ~user
+ // URL: ftp://user@server/%2F -> /
+ // ^- this '/' is just a separator
+ Url newurl( _url );
+ newurl.setPathName( ( Pathname("./"+_url.getPathName()) / filename_r ).asString().substr(1) );
return newurl;
}
///////////////////////////////////////////////////////////////////
-void MediaCurl::getFile( const Pathname & filename ) const
+void MediaCurl::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
{
// Use absolute file name to prevent access of files outside of the
// hierarchy below the attach point.
- getFileCopy(filename, localPath(filename).absolutename());
+ getFileCopy(filename, localPath(filename).absolutename(), expectedFileSize_r);
}
///////////////////////////////////////////////////////////////////
-void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target) const
+void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target, const ByteCount &expectedFileSize_r ) const
{
callback::SendReport<DownloadProgressReport> report;
{
try
{
- doGetFileCopy(filename, target, report);
+ doGetFileCopy(filename, target, report, expectedFileSize_r);
retry = false;
}
// retry with proper authentication data
// unexpected exception
catch (MediaException & excpt_r)
{
- // FIXME: error number fix
- report->finish(fileurl, zypp::media::DownloadProgressReport::ERROR, excpt_r.asUserHistory());
+ media::DownloadProgressReport::Error reason = media::DownloadProgressReport::ERROR;
+ if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) ||
+ typeid(excpt_r) == typeid( media::MediaNotAFileException ) )
+ {
+ reason = media::DownloadProgressReport::NOT_FOUND;
+ }
+ report->finish(fileurl, reason, excpt_r.asUserHistory());
ZYPP_RETHROW(excpt_r);
}
}
///////////////////////////////////////////////////////////////////
-void MediaCurl::evaluateCurlCode( const Pathname &filename,
+void MediaCurl::evaluateCurlCode(const Pathname &filename,
CURLcode code,
- bool timeout_reached ) const
+ bool timeout_reached) const
{
if ( code != 0 )
{
url = _url;
else
url = getFileUrl(filename);
+
std::string err;
- try
{
switch ( code )
{
case CURLE_UNSUPPORTED_PROTOCOL:
+ err = " Unsupported protocol";
+ if ( !_lastRedirect.empty() )
+ {
+ err += " or redirect (";
+ err += _lastRedirect;
+ err += ")";
+ }
+ break;
case CURLE_URL_MALFORMAT:
case CURLE_URL_MALFORMAT_USER:
err = " Bad URL";
));
}
+ case 502: // bad gateway (bnc #1070851)
case 503: // service temporarily unavailable (bnc #462545)
ZYPP_THROW(MediaTemporaryProblemException(url));
case 504: // gateway timeout
ZYPP_THROW(MediaForbiddenException(url, msg403));
}
case 404:
+ case 410:
ZYPP_THROW(MediaFileNotFoundException(_url, filename));
}
case CURLE_REMOTE_FILE_NOT_FOUND:
#endif
case CURLE_FTP_ACCESS_DENIED:
+ case CURLE_TFTP_NOTFOUND:
err = "File not found";
ZYPP_THROW(MediaFileNotFoundException(_url, filename));
break;
break;
case CURLE_SSL_PEER_CERTIFICATE:
default:
- err = "Unrecognized error";
+ err = "Curl error " + str::numstring( code );
break;
}
// uhm, no 0 code but unknown curl exception
ZYPP_THROW(MediaCurlException(url, err, _curlError));
}
- catch (const MediaException & excpt_r)
- {
- ZYPP_RETHROW(excpt_r);
- }
}
else
{
// encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
// contains an absolute path.
//
+ _lastRedirect.clear();
string urlBuffer( curlUrl.asString());
CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
urlBuffer.c_str() );
///////////////////////////////////////////////////////////////////
-void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaCurl::doGetFileCopy(const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
{
Pathname dest = target.absolutename();
if( assert_dir( dest.dirname() ) )
}
try
{
- doGetFileCopyFile(filename, dest, file, report, options);
+ doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
}
catch (Exception &e)
{
{
DBG << "HTTP response: " + str::numstring(httpReturnCode);
if ( httpReturnCode == 304
- || ( httpReturnCode == 213 && _url.getScheme() == "ftp" ) ) // not modified
+ || ( httpReturnCode == 213 && (_url.getScheme() == "ftp" || _url.getScheme() == "tftp") ) ) // not modified
{
DBG << " Not modified.";
modified = false;
///////////////////////////////////////////////////////////////////
-void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaCurl::doGetFileCopyFile(const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
{
DBG << filename.asString() << endl;
// encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file"
// contains an absolute path.
//
+ _lastRedirect.clear();
string urlBuffer( curlUrl.asString());
CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
urlBuffer.c_str() );
}
// Set callback and perform.
- ProgressData progressData(_curl, _settings.timeout(), url, &report);
+ ProgressData progressData(_curl, _settings.timeout(), url, expectedFileSize_r, &report);
if (!(options & OPTION_NO_REPORT_START))
report->start(url, dest);
if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) {
<< " bytes." << endl;
// the timeout is determined by the progress data object
- // which holds wheter the timeout was reached or not,
+ // which holds whether the timeout was reached or not,
// otherwise it would be a user cancel
try {
- evaluateCurlCode( filename, ret, progressData.reached);
+
+ if ( progressData.fileSizeExceeded )
+ ZYPP_THROW(MediaFileSizeExceededException(url, progressData._expectedFileSize));
+
+ evaluateCurlCode( filename, ret, progressData.reached );
}
catch ( const MediaException &e ) {
// some error, we are not sure about file existence, rethrw
switch ( it->type ) {
case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
case filesystem::FT_FILE:
- getFile( filename );
+ getFile( filename, 0 );
break;
case filesystem::FT_DIR: // newer directory.yast contain at least directory info
if ( recurse_r ) {
}
///////////////////////////////////////////////////////////////////
+//
+int MediaCurl::aliveCallback( void *clientp, double /*dltotal*/, double dlnow, double /*ultotal*/, double /*ulnow*/ )
+{
+ ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
+ if( pdata )
+ {
+ // Do not propagate dltotal in alive callbacks. MultiCurl uses this to
+ // prevent a percentage raise while downloading a metalink file. Download
+ // activity however is indicated by propagating the download rate (via dlnow).
+ pdata->updateStats( 0.0, dlnow );
+ return pdata->reportProgress();
+ }
+ return 0;
+}
-int MediaCurl::progressCallback( void *clientp,
- double dltotal, double dlnow,
- double ultotal, double ulnow)
+int MediaCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
{
- ProgressData *pdata = reinterpret_cast<ProgressData *>(clientp);
- if( pdata)
+ ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
+ if( pdata )
{
// work around curl bug that gives us old data
- long httpReturnCode = 0;
- if (curl_easy_getinfo(pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode) != CURLE_OK || httpReturnCode == 0)
- return 0;
-
- time_t now = time(NULL);
- if( now > 0)
- {
- // reset time of last change in case initial time()
- // failed or the time was adjusted (goes backward)
- if( pdata->ltime <= 0 || pdata->ltime > now)
- {
- pdata->ltime = now;
- }
-
- // start time counting as soon as first data arrives
- // (skip the connection / redirection time at begin)
- time_t dif = 0;
- if (dlnow > 0 || ulnow > 0)
- {
- dif = (now - pdata->ltime);
- dif = dif > 0 ? dif : 0;
-
- pdata->secs += dif;
- }
-
- // update the drate_avg and drate_period only after a second has passed
- // (this callback is called much more often than a second)
- // otherwise the values would be far from accurate when measuring
- // the time in seconds
- //! \todo more accurate download rate computationn, e.g. compute average value from last 5 seconds, or work with milliseconds instead of seconds
-
- if ( pdata->secs > 1 && (dif > 0 || dlnow == dltotal ))
- pdata->drate_avg = (dlnow / pdata->secs);
-
- if ( dif > 0 )
- {
- pdata->drate_period = ((dlnow - pdata->dload_period) / dif);
- pdata->dload_period = dlnow;
- }
- }
-
- // send progress report first, abort transfer if requested
- if( pdata->report)
- {
- if (!(*(pdata->report))->progress(int( dltotal ? dlnow * 100 / dltotal : 0 ),
- pdata->url,
- pdata->drate_avg,
- pdata->drate_period))
- {
- return 1; // abort transfer
- }
- }
-
- // check if we there is a timeout set
- if( pdata->timeout > 0)
- {
- if( now > 0)
- {
- bool progress = false;
-
- // update download data if changed, mark progress
- if( dlnow != pdata->dload)
- {
- progress = true;
- pdata->dload = dlnow;
- pdata->ltime = now;
- }
- // update upload data if changed, mark progress
- if( ulnow != pdata->uload)
- {
- progress = true;
- pdata->uload = ulnow;
- pdata->ltime = now;
- }
+ long httpReturnCode = 0;
+ if ( curl_easy_getinfo( pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0 )
+ return aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow );
- if( !progress && (now >= (pdata->ltime + pdata->timeout)))
- {
- pdata->reached = true;
- return 1; // aborts transfer
- }
- }
- }
+ pdata->updateStats( dltotal, dlnow );
+ return pdata->reportProgress();
}
return 0;
}
return "";
}
+/**
+ * MediaMultiCurl needs to reset the expected filesize in case a metalink file is downloaded
+ * otherwise this function should not be called
+ */
+void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
+{
+ ProgressData *data = reinterpret_cast<ProgressData *>(clientp);
+ if ( data ) {
+ data->_expectedFileSize = expectedFileSize;
+ }
+}
+
///////////////////////////////////////////////////////////////////
bool MediaCurl::authenticate(const string & availAuthTypes, bool firstTry) const
{
//! \todo need a way to pass different CredManagerOptions here
- Target_Ptr target = zypp::getZYpp()->getTarget();
- CredentialManager cm(CredManagerOptions(target ? target->root() : ""));
+ CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot()));
CurlAuthData_Ptr credentials;
// get stored credentials
// indicate we have no good credentials from CM
cmcred.reset();
- string prompt_msg = boost::str(boost::format(
- //!\todo add comma to the message for the next release
- _("Authentication required for '%s'")) % _url.asString());
+ string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString();
// set available authentication types from the exception
// might be needed in prompt