21#include <zypp-core/parser/Sysconfig>
28#include <zypp-curl/ProxyInfo>
29#include <zypp-curl/auth/CurlAuthData>
30#include <zypp-media/auth/CredentialManager>
31#include <zypp-curl/CurlConfig>
54#ifdef ENABLE_ZCHUNK_COMPRESSION
72 using clock = std::chrono::steady_clock;
88 clock::time_point now = clock::now();
97 if ( dlnow && dlnow !=
_dnlNow ) {
129 const Pathname & attach_point_hint_r )
137 MIL <<
"MediaCurl2::MediaCurl2(" << url_r <<
", " << attach_point_hint_r <<
")" << endl;
143 char *atemp = ::strdup( apath.
asString().c_str());
146 atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
148 WAR <<
"attach point " << ainfo.
path()
149 <<
" is not useable for " << url_r.
getScheme() << endl;
152 else if( atest != NULL)
173 if ( !zyppng::NetworkRequestDispatcher::supportsProtocol (
url ) )
175 std::string msg(
"Unsupported protocol '");
176 msg +=
url.getScheme();
215 if ( cred && cred->valid() ) {
228 if ( !
_url.isValid() )
280 const auto &filename = srcFile.
filename();
318 if(
_url.getHost().empty())
323 DBG <<
"URL: " <<
url.asString() << endl;
331 auto req = std::make_shared<zyppng::NetworkRequest>( curlUrl,
"/dev/null" );
350 return ( !req->hasError() );
358 if( assert_dir( dest.
dirname() ) ) {
359 DBG <<
"assert_dir " << dest.
dirname() <<
" failed" << endl;
366 ERR <<
"out of memory for temp file name" << endl;
370 AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
372 ERR <<
"mkstemp failed for file '" << destNew <<
"'" << endl;
378 DBG <<
"dest: " << dest << endl;
379 DBG <<
"temp: " << destNew << endl;
381 Not implemented here yet because NetworkRequest can not
do IFMODSINCE yet
385 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
386 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (
long)
PathInfo(
target).mtime());
390 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
391 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
400 if(
_url.getHost().empty())
405 DBG <<
"URL: " <<
url.asString() << endl;
416#ifdef ENABLE_ZCHUNK_COMPRESSION
420 req->resetRequestRanges();
425 Also disabled IFMODSINCE code, see above
while not yet implemented here
426 #if CURLVERSION_AT_LEAST(7,19,4)
431 if ( ftell(file) == 0 && ret == 0 )
433 long httpReturnCode = 33;
434 if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 )
436 long conditionUnmet = 33;
437 if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet )
439 WAR <<
"TIMECONDITION unmet - retry without." << endl;
440 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
441 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
453 ERR <<
"Failed to chmod file " << destNew << endl;
457 if ( rename( destNew, dest ) != 0 ) {
458 ERR <<
"Rename failed" << endl;
461 destNew.resetDispose();
469#ifdef ENABLE_ZCHUNK_COMPRESSION
477 std::optional<zypp::Digest> digest;
481 if ( !headerSum.empty () ) {
483 if ( !digest->create( headerSum.type() ) ) {
484 ERR <<
"Unknown header checksum type " << headerSum.type() << std::endl;
487 sum = zypp::Digest::hexStringToUByteArray( headerSum.checksum() );
490 req->addRequestRange( 0, srcFile.
headerSize(), std::move(digest), sum );
493 req->resetRequestRanges();
498 ERR <<
"Failed to setup zchunk because of: " << res._message << std::endl;
509 for (
const auto &block : res._blocks ) {
510 if ( block._checksum.size() && block._chksumtype.size() ) {
512 if ( !dig->create( block._chksumtype ) ) {
513 WAR_MEDIA <<
"Trying to create Digest with chksum type " << block._chksumtype <<
" failed " << std::endl;
519 req->addRequestRange( block._start, block._len, std::move(dig), block._checksum, {}, block._relevantDigestLen, block._chksumPad );
528 ERR <<
"ZCK failed with error: " << err << std::endl;
546 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
547 Pathname filename = dirname + it->name;
550 switch ( it->type ) {
557 getDir( filename, recurse_r );
559 res = assert_dir(
localPath( filename ) );
561 WAR <<
"Ignore error (" << res <<
") on creating local directory '" <<
localPath( filename ) <<
"'" << endl;
575 const Pathname & dirname,
bool dots )
const
583 const Pathname & dirname,
bool dots )
const
594 bool firstAuth =
true;
599 std::optional<internal::ProgressTracker> progTracker;
601 std::vector<zyppng::connection> signalConnections {
603 if ( !report)
return;
607 if ( !report || !progTracker )
610 progTracker->updateStats( dlTotal, dlNow );
611 if ( !(*report)->progress( progTracker->_dnlPercent, req.
url(), progTracker-> _drateTotal, progTracker->_drateLast ) )
622 std::for_each( signalConnections.begin(), signalConnections.end(), [](
auto &conn ) { conn.disconnect(); });
623 signalConnections.clear();
641 if ( req->hasError() ) {
643 std::exception_ptr excp;
644 const auto &error = req->error();
645 switch ( error.type() ) {
689 std::string authHint = error.extraInfoValue(
"authHint", std::string());
702 DBG <<
"BUG: Download error flag is set , but Error code is NoError" << std::endl;
712 if ( maxTries > 0 ) {
717 if ( report ) (*report)->finish( req->url(), errCode, error.toString() );
718 std::rethrow_exception( excp );
738 if (cmcred && firstTry)
741 DBG <<
"got stored credentials:" << endl << *credentials << endl;
752 if (!
_url.getUsername().empty() && firstTry)
753 curlcred->setUsername(
_url.getUsername());
756 curlcred->setUsername(cmcred->username());
761 std::string prompt_msg =
str::Format(
_(
"Authentication required for '%s'")) %
_url.asString();
765 curlcred->setAuthType(availAuthTypes);
768 if (auth_report->prompt(
_url, prompt_msg, *curlcred))
770 DBG <<
"callback answer: retry" << endl
771 <<
"CurlAuthData: " << *curlcred << endl;
773 if (curlcred->valid())
775 credentials = curlcred;
789 DBG <<
"callback answer: cancel" << endl;
800 if (credentials->authType() == CURLAUTH_NONE)
801 credentials->setAuthType(availAuthTypes);
804 if (credentials->authType() != CURLAUTH_NONE) {
810 credentials->setUrl(
_url);
Compute Message Digests (MD5, SHA1 etc)
static std::string digestVectorToString(const UByteArray &vec)
get hex string representation of the digest vector given as parameter
Base class for Exception.
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
std::string getScheme() const
Returns the scheme name of the URL.
static ZConfig & instance()
Singleton ctor.
Wrapper class for stat/lstat.
const Pathname & path() const
Return current Pathname.
Pathname dirname() const
Return all but the last component od this path.
const std::string & asString() const
String representation.
bool empty() const
Test for an empty path.
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
The NetworkRequestError class Represents a error that occured in.
const zypp::Pathname & targetFilePath() const
Returns the target filename path.
SignalProxy< void(NetworkRequest &req, const NetworkRequestError &err)> sigFinished()
Signals that the download finished.
SignalProxy< void(NetworkRequest &req, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow)> sigProgress()
Signals if there was data read from the download.
static bool validateZckFile(const zypp::Pathname &file, std::string &error)
static bool isZchunkFile(const zypp::Pathname &file)
static PrepareResult prepareZck(const zypp::Pathname &delta, const zypp::Pathname &target, const zypp::ByteCount &expectedFileSize)
void fillSettingsFromUrl(const Url &url, media::TransferSettings &s)
Fills the settings structure using options passed on the url for example ?timeout=x&proxy=foo.
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)
const long & ZYPP_MEDIA_CURL_DEBUG()
const long& for setting CURLOPT_DEBUGDATA Returns a reference to a static variable,...
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
std::list< DirEntry > DirContent
Returned by readdir.
int unlink(const Pathname &path)
Like 'unlink'.
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
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.
Bottleneck filtering all DownloadProgressReport issued from Media[Muli]Curl.
double _drateLast
Download rate in last period.
double _drateTotal
Download rate so far.
void updateStats(double dltotal=0.0, double dlnow=0.0)
double _dnlTotal
Bytes to download or 0 if unknown.
double _dnlLast
Bytes downloaded at period start.
std::chrono::steady_clock clock
double _dnlNow
Bytes downloaded now.
int _dnlPercent
Percent completed or 0 if _dnlTotal is unknown.
std::optional< clock::time_point > _timeStart
Start total stats.
std::optional< clock::time_point > _timeLast
Start last period(~1sec)
AutoDispose<int> calling ::close
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.