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>
55#ifdef ENABLE_ZCHUNK_COMPRESSION
76 const Pathname & attach_point_hint_r )
84 MIL <<
"MediaCurl2::MediaCurl2(" << url_r <<
", " << attach_point_hint_r <<
")" << endl;
90 char *atemp = ::strdup( apath.
asString().c_str());
93 atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
95 WAR <<
"attach point " << ainfo.
path()
96 <<
" is not useable for " << url_r.
getScheme() << endl;
99 else if( atest != NULL)
113 return ::internal::clearQueryString(
url);
120 if ( !zyppng::NetworkRequestDispatcher::supportsProtocol (
url ) )
122 std::string msg(
"Unsupported protocol '");
123 msg +=
url.getScheme();
162 if ( cred && cred->valid() ) {
175 if ( !
_url.isValid() )
227 const auto &filename = srcFile.
filename();
265 if(
_url.getHost().empty())
270 DBG <<
"URL: " <<
url.asString() << endl;
278 auto req = std::make_shared<zyppng::NetworkRequest>( curlUrl,
"/dev/null" );
297 return ( !req->hasError() );
305 if( assert_dir( dest.
dirname() ) ) {
306 DBG <<
"assert_dir " << dest.
dirname() <<
" failed" << endl;
313 ERR <<
"out of memory for temp file name" << endl;
317 AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
319 ERR <<
"mkstemp failed for file '" << destNew <<
"'" << endl;
325 DBG <<
"dest: " << dest << endl;
326 DBG <<
"temp: " << destNew << endl;
328 Not implemented here yet because NetworkRequest can not
do IFMODSINCE yet
332 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
333 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (
long)
PathInfo(
target).mtime());
337 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
338 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
347 if(
_url.getHost().empty())
352 DBG <<
"URL: " <<
url.asString() << endl;
363#ifdef ENABLE_ZCHUNK_COMPRESSION
367 req->resetRequestRanges();
372 Also disabled IFMODSINCE code, see above
while not yet implemented here
373 #if CURLVERSION_AT_LEAST(7,19,4)
378 if ( ftell(file) == 0 && ret == 0 )
380 long httpReturnCode = 33;
381 if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 )
383 long conditionUnmet = 33;
384 if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet )
386 WAR <<
"TIMECONDITION unmet - retry without." << endl;
387 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
388 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
400 ERR <<
"Failed to chmod file " << destNew << endl;
404 if ( rename( destNew, dest ) != 0 ) {
405 ERR <<
"Rename failed" << endl;
408 destNew.resetDispose();
416#ifdef ENABLE_ZCHUNK_COMPRESSION
424 std::optional<zypp::Digest> digest;
428 if ( !headerSum.empty () ) {
430 if ( !digest->create( headerSum.type() ) ) {
431 ERR <<
"Unknown header checksum type " << headerSum.type() << std::endl;
434 sum = zypp::Digest::hexStringToUByteArray( headerSum.checksum() );
437 req->addRequestRange( 0, srcFile.
headerSize(), std::move(digest), sum );
440 req->resetRequestRanges();
445 ERR <<
"Failed to setup zchunk because of: " << res._message << std::endl;
456 for (
const auto &block : res._blocks ) {
457 if ( block._checksum.size() && block._chksumtype.size() ) {
459 if ( !dig->create( block._chksumtype ) ) {
460 WAR_MEDIA <<
"Trying to create Digest with chksum type " << block._chksumtype <<
" failed " << std::endl;
466 req->addRequestRange( block._start, block._len, std::move(dig), block._checksum, {}, block._relevantDigestLen, block._chksumPad );
475 ERR <<
"ZCK failed with error: " << err << std::endl;
493 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
494 Pathname filename = dirname + it->name;
497 switch ( it->type ) {
504 getDir( filename, recurse_r );
506 res = assert_dir(
localPath( filename ) );
508 WAR <<
"Ignore error (" << res <<
") on creating local directory '" <<
localPath( filename ) <<
"'" << endl;
522 const Pathname & dirname,
bool dots )
const
530 const Pathname & dirname,
bool dots )
const
541 bool firstAuth =
true;
546 std::optional<internal::ProgressTracker> progTracker;
548 std::vector<zyppng::connection> signalConnections {
550 if ( !report)
return;
554 if ( !report || !progTracker )
557 progTracker->updateStats( dlTotal, dlNow );
558 if ( !(*report)->progress( progTracker->_dnlPercent, req.
url(), progTracker-> _drateTotal, progTracker->_drateLast ) )
569 std::for_each( signalConnections.begin(), signalConnections.end(), [](
auto &conn ) { conn.disconnect(); });
570 signalConnections.clear();
588 if ( req->hasError() ) {
590 std::exception_ptr excp;
591 const auto &error = req->error();
592 switch ( error.type() ) {
636 std::string authHint = error.extraInfoValue(
"authHint", std::string());
649 DBG <<
"BUG: Download error flag is set , but Error code is NoError" << std::endl;
659 if ( maxTries > 0 ) {
664 if ( report ) (*report)->finish( req->url(), errCode, error.toString() );
665 std::rethrow_exception( excp );
689 if (cmcred && firstTry)
692 DBG <<
"got stored credentials:" << endl << *credentials << endl;
703 if (!
url.getUsername().empty() && firstTry)
704 curlcred->setUsername(
url.getUsername());
707 curlcred->setUsername(cmcred->username());
712 std::string prompt_msg =
str::Format(
_(
"Authentication required for '%s'")) %
url.asString();
716 curlcred->setAuthType(availAuthTypes);
719 if (auth_report->prompt(
url, prompt_msg, *curlcred))
721 DBG <<
"callback answer: retry" << endl
722 <<
"CurlAuthData: " << *curlcred << endl;
724 if (curlcred->valid())
726 credentials = curlcred;
740 DBG <<
"callback answer: cancel" << endl;
747 settings.setUsername(credentials->username());
748 settings.setPassword(credentials->password());
751 if (credentials->authType() == CURLAUTH_NONE)
752 credentials->setAuthType(availAuthTypes);
755 if (credentials->authType() != CURLAUTH_NONE) {
756 settings.setAuthType(credentials->authTypeAsString());
761 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.
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.
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.