libzypp: zypp/media/MediaCurl2.cc Source File

libzypp 17.36.6

MediaCurl2.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
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 <zypp-core/parser/Sysconfig>
22#include <zypp/base/Gettext.h>
23
24#include <zypp/media/MediaCurl2.h>
25
26#include <zypp-core/zyppng/base/private/linuxhelpers_p.h>
27#include <zypp-core/base/userrequestexception.h>
28#include <zypp-curl/ProxyInfo>
29#include <zypp-curl/auth/CurlAuthData>
30#include <zypp-media/auth/CredentialManager>
31#include <zypp-curl/CurlConfig>
32#include <zypp-curl/private/curlhelper_p.h>
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 <zypp-core/zyppng/base/eventloop.h>
39#include <zypp-core/zyppng/base/private/threaddata_p.h>
40#include <zypp-curl/ng/network/networkrequestdispatcher.h>
41#include <zypp-curl/ng/network/request.h>
42
43#include <cstdlib>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <sys/mount.h>
47#include <dirent.h>
48#include <unistd.h>
49#include <glib.h>
50
51#include "detail/DownloadProgressTracker.h"
52#include "detail/OptionalDownloadProgressReport.h"
53#include "zypp-curl/ng/network/private/mediadebug_p.h"
54
55#ifdef ENABLE_ZCHUNK_COMPRESSION
56#include <zypp-curl/ng/network/zckhelper.h>
57#endif
58
59
65
66using std::endl;
67
68using namespace internal;
69using namespace zypp::base;
70
71namespace zypp {
72
73 namespace media {
74
75 MediaCurl2::MediaCurl2( const Url & url_r,
76 const Pathname & attach_point_hint_r )
77 : MediaNetworkCommonHandler( url_r, attach_point_hint_r,
78 "/", // urlpath at attachpoint
79 true ) // does_download
80 , _evDispatcher( zyppng::ThreadData::current().ensureDispatcher() )
81 , _nwDispatcher( std::make_shared<zyppng::NetworkRequestDispatcher>() )
82 {
83
84 MIL << "MediaCurl2::MediaCurl2(" << url_r << ", " << attach_point_hint_r << ")" << endl;
85
86 if( !attachPoint().empty())
87 {
88 PathInfo ainfo(attachPoint());
89 Pathname apath(attachPoint() + "XXXXXX");
90 char *atemp = ::strdup( apath.asString().c_str());
91 char *atest = NULL;
92 if( !ainfo.isDir() || !ainfo.userMayRWX() ||
93 atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
94 {
95 WAR << "attach point " << ainfo.path()
96 << " is not useable for " << url_r.getScheme() << endl;
97 setAttachPoint("", true);
98 }
99 else if( atest != NULL)
100 ::rmdir(atest);
101
102 if( atemp != NULL)
103 ::free(atemp);
104 }
105
106 _nwDispatcher->setAgentString ( str::asString( agentString () ) );
107 _nwDispatcher->setHostSpecificHeader ("download.opensuse.org", "X-ZYpp-DistributionFlavor", str::asString(distributionFlavorHeader()) );
108 _nwDispatcher->setHostSpecificHeader ("download.opensuse.org", "X-ZYpp-AnonymousId", str::asString(anonymousIdHeader()) );
109 }
110
111 Url MediaCurl2::clearQueryString(const Url &url) const
112 {
113 return ::internal::clearQueryString(url);
114 }
115
117
118 void MediaCurl2::checkProtocol(const Url &url) const
119 {
120 if ( !zyppng::NetworkRequestDispatcher::supportsProtocol ( url ) )
121 {
122 std::string msg("Unsupported protocol '");
123 msg += url.getScheme();
124 msg += "'";
125 ZYPP_THROW(MediaBadUrlException(_url, msg));
126 }
127 }
128
129 void MediaCurl2::setupEasy()
130 {
131 // fill some settings from url query parameters
132 try
133 {
134 _effectiveSettings = _settings;
135 fillSettingsFromUrl(_url, _effectiveSettings);
136 }
137 catch ( const MediaException &e )
138 {
139 disconnectFrom();
140 ZYPP_RETHROW(e);
141 }
142 // if the proxy was not set (or explicitly unset) by url, then look...
143 if ( _effectiveSettings.proxy().empty() )
144 {
145 // ...at the system proxy settings
146 fillSettingsSystemProxy(_url, _effectiveSettings);
147 }
148
149 /* Fixes bsc#1174011 "auth=basic ignored in some cases"
150 * We should proactively add the password to the request if basic auth is configured
151 * and a password is available in the credentials but not in the URL.
152 *
153 * We will be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route
154 * and ask the server first about the auth method
155 */
156 if ( _effectiveSettings.authType() == "basic"
157 && _effectiveSettings.username().size()
158 && !_effectiveSettings.password().size() ) {
159
160 CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot()));
161 const auto cred = cm.getCred( _url );
162 if ( cred && cred->valid() ) {
163 if ( !_effectiveSettings.username().size() )
164 _effectiveSettings.setUsername(cred->username());
165 _effectiveSettings.setPassword(cred->password());
166 }
167 }
168 }
169
170 void MediaCurl2::attachTo (bool next)
171 {
172 if ( next )
173 ZYPP_THROW(MediaNotSupportedException(_url));
174
175 if ( !_url.isValid() )
176 ZYPP_THROW(MediaBadUrlException(_url));
177
178 checkProtocol(_url);
179 if( !isUseableAttachPoint( attachPoint() ) )
180 {
181 setAttachPoint( createAttachPoint(), true );
182 }
183
184 disconnectFrom(); // clean state if needed
185
186 // here : setup TransferSettings
187 setupEasy();
188
189 // FIXME: need a derived class to propelly compare url's
190 MediaSourceRef media( new MediaSource(_url.getScheme(), _url.asString()));
191 setMediaSource(media);
192 }
193
194 bool
195 MediaCurl2::checkAttachPoint(const Pathname &apoint) const
196 {
197 return MediaHandler::checkAttachPoint( apoint, true, true);
198 }
199
200 void MediaCurl2::disconnectFrom()
201 {
202 // clear effective settings
203 _effectiveSettings = _settings;
204 }
205
207
208 void MediaCurl2::releaseFrom( const std::string & ejectDev )
209 {
210 disconnect();
211 }
212
214
215 void MediaCurl2::getFile( const OnMediaLocation &file ) const
216 {
217 // Use absolute file name to prevent access of files outside of the
218 // hierarchy below the attach point.
219 getFileCopy( file, localPath(file.filename()).absolutename() );
220 }
221
223
224 void MediaCurl2::getFileCopy( const OnMediaLocation & srcFile , const Pathname & target ) const
225 {
226
227 const auto &filename = srcFile.filename();
228
229 // Optional files will send no report until data are actually received (we know it exists).
230 OptionalDownloadProgressReport reportfilter( srcFile.optional() );
231 callback::SendReport<DownloadProgressReport> report;
232
233 Url fileurl(getFileUrl(filename));
234 do
235 {
236 try
237 {
238 doGetFileCopy( srcFile, target, report );
239 break; // success!
240 }
241 // unexpected exception
242 catch (MediaException & excpt_r)
243 {
244 media::DownloadProgressReport::Error reason = media::DownloadProgressReport::ERROR;
245 if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) ||
246 typeid(excpt_r) == typeid( media::MediaNotAFileException ) )
247 {
248 reason = media::DownloadProgressReport::NOT_FOUND;
249 }
250 report->finish(fileurl, reason, excpt_r.asUserHistory());
251 ZYPP_RETHROW(excpt_r);
252 }
253 }
254 while ( true );
255 report->finish(fileurl, zypp::media::DownloadProgressReport::NO_ERROR, "");
256 }
257
258 bool MediaCurl2::getDoesFileExist( const Pathname & filename ) const
259 {
260 DBG << filename.asString() << endl;
261
262 if(!_url.isValid())
263 ZYPP_THROW(MediaBadUrlException(_url));
264
265 if(_url.getHost().empty())
266 ZYPP_THROW(MediaBadUrlEmptyHostException(_url));
267
268 Url url(getFileUrl(filename));
269
270 DBG << "URL: " << url.asString() << endl;
271
272 // Use URL without options and without username and passwd
273 // (some proxies dislike them in the URL).
274 // Curl seems to need the just scheme, hostname and a path;
275 // the rest was already passed as curl options (in attachTo).
276 Url curlUrl( clearQueryString(url) );
277
278 auto req = std::make_shared<zyppng::NetworkRequest>( curlUrl, "/dev/null" );
279 req->setOptions ( zyppng::NetworkRequest::HeadRequest ); // just check for existance
280
281 // as we are not having user interaction, the user can't cancel
282 // the file existence checking, a callback or timeout return code
283 // will be always a timeout.
284 try {
285 const_cast<MediaCurl2*>(this)->executeRequest ( req );
286 }
287 catch ( const MediaFileNotFoundException &e ) {
288 // if the file did not exist then we can return false
289 return false;
290 }
291 catch ( const MediaException &e ) {
292 // some error, we are not sure about file existence, rethrw
293 ZYPP_RETHROW(e);
294 }
295
296 // exists
297 return ( !req->hasError() );
298 }
299
301
302 void MediaCurl2::doGetFileCopy( const OnMediaLocation &srcFile , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
303 {
304 Pathname dest = target.absolutename();
305 if( assert_dir( dest.dirname() ) ) {
306 DBG << "assert_dir " << dest.dirname() << " failed" << endl;
307 ZYPP_THROW( MediaSystemException(getFileUrl(srcFile.filename()), "System error on " + dest.dirname().asString()) );
308 }
309
310 ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) }; {
311 AutoFREE<char> buf { ::strdup( (*destNew).c_str() ) };
312 if( ! buf ) {
313 ERR << "out of memory for temp file name" << endl;
314 ZYPP_THROW(MediaSystemException(getFileUrl(srcFile.filename()), "out of memory for temp file name"));
315 }
316
317 AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
318 if( tmp_fd == -1 ) {
319 ERR << "mkstemp failed for file '" << destNew << "'" << endl;
320 ZYPP_THROW(MediaWriteException(destNew));
321 }
322 destNew = ManagedFile( (*buf), filesystem::unlink );
323 }
324
325 DBG << "dest: " << dest << endl;
326 DBG << "temp: " << destNew << endl;
327#if 0
328 Not implemented here yet because NetworkRequest can not do IFMODSINCE yet
329 // set IFMODSINCE time condition (no download if not modified)
330 if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) )
331 {
332 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
333 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime());
334 }
335 else
336 {
337 curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
338 curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L);
339 }
340#endif
341
342 DBG << srcFile.filename().asString() << endl;
343
344 if(!_url.isValid())
345 ZYPP_THROW(MediaBadUrlException(_url));
346
347 if(_url.getHost().empty())
348 ZYPP_THROW(MediaBadUrlEmptyHostException(_url));
349
350 Url url(getFileUrl(srcFile.filename()));
351
352 DBG << "URL: " << url.asString() << endl;
353 // Use URL without options and without username and passwd
354 // (some proxies dislike them in the URL).
355 // Curl seems to need the just scheme, hostname and a path;
356 // the rest was already passed as curl options (in attachTo).
357 Url curlUrl( clearQueryString(url) );
358
359 auto req = std::make_shared<zyppng::NetworkRequest>( curlUrl, destNew, zyppng::NetworkRequest::WriteShared /*do not truncate*/ );
360 req->setExpectedFileSize ( srcFile.downloadSize () );
361
362 bool done = false;
363#ifdef ENABLE_ZCHUNK_COMPRESSION
364 done = const_cast<MediaCurl2*>(this)->tryZchunk(req, srcFile, destNew, report);
365#endif
366 if ( !done ) {
367 req->resetRequestRanges();
368 const_cast<MediaCurl2 *>(this)->executeRequest ( req, &report );
369 }
370
371#if 0
372 Also disabled IFMODSINCE code, see above while not yet implemented here
373 #if CURLVERSION_AT_LEAST(7,19,4)
374 // bnc#692260: If the client sends a request with an If-Modified-Since header
375 // with a future date for the server, the server may respond 200 sending a
376 // zero size file.
377 // curl-7.19.4 introduces CURLINFO_CONDITION_UNMET to check this condition.
378 if ( ftell(file) == 0 && ret == 0 )
379 {
380 long httpReturnCode = 33;
381 if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 )
382 {
383 long conditionUnmet = 33;
384 if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet )
385 {
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);
389 ret = executeCurl();
390 }
391 }
392 }
393#endif
394#endif
395
396
397 // apply umask
398 if ( ::chmod( destNew->c_str(), filesystem::applyUmaskTo( 0644 ) ) )
399 {
400 ERR << "Failed to chmod file " << destNew << endl;
401 }
402
403 // move the temp file into dest
404 if ( rename( destNew, dest ) != 0 ) {
405 ERR << "Rename failed" << endl;
406 ZYPP_THROW(MediaWriteException(dest));
407 }
408 destNew.resetDispose(); // no more need to unlink it
409
410 DBG << "done: " << PathInfo(dest) << endl;
411 }
412
413
414 bool MediaCurl2::tryZchunk( zyppng::NetworkRequestRef req, const OnMediaLocation &srcFile, const Pathname &target, callback::SendReport<DownloadProgressReport> &report )
415 {
416#ifdef ENABLE_ZCHUNK_COMPRESSION
417
418 // HERE add zchunk logic if required
419 if ( !srcFile.deltafile().empty()
420 && zyppng::ZckHelper::isZchunkFile (srcFile.deltafile ())
421 && srcFile.headerSize () > 0 ) {
422
423 // first fetch the zck header
424 std::optional<zypp::Digest> digest;
425 UByteArray sum;
426
427 const auto &headerSum = srcFile.headerChecksum();
428 if ( !headerSum.empty () ) {
429 digest = zypp::Digest();
430 if ( !digest->create( headerSum.type() ) ) {
431 ERR << "Unknown header checksum type " << headerSum.type() << std::endl;
432 return false;
433 }
434 sum = zypp::Digest::hexStringToUByteArray( headerSum.checksum() );
435 }
436
437 req->addRequestRange( 0, srcFile.headerSize(), std::move(digest), sum );
438 executeRequest ( req, nullptr );
439
440 req->resetRequestRanges();
441
442 auto res = zyppng::ZckHelper::prepareZck( srcFile.deltafile(), target, srcFile.downloadSize() );
443 switch(res._code) {
444 case zyppng::ZckHelper::PrepareResult::Error: {
445 ERR << "Failed to setup zchunk because of: " << res._message << std::endl;
446 return false;
447 }
448 case zyppng::ZckHelper::PrepareResult::NothingToDo:
449 return true; // already done
450 case zyppng::ZckHelper::PrepareResult::ExceedsMaxLen:
451 ZYPP_THROW( MediaFileSizeExceededException( req->url(), srcFile.downloadSize(), res._message ));
452 case zyppng::ZckHelper::PrepareResult::Success:
453 break;
454 }
455
456 for ( const auto &block : res._blocks ) {
457 if ( block._checksum.size() && block._chksumtype.size() ) {
458 std::optional<zypp::Digest> dig = zypp::Digest();
459 if ( !dig->create( block._chksumtype ) ) {
460 WAR_MEDIA << "Trying to create Digest with chksum type " << block._chksumtype << " failed " << std::endl;
461 return false;
462 }
463
464 if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 )
465 DBG_MEDIA << "Starting block " << block._start << " with checksum " << zypp::Digest::digestVectorToString( block._checksum ) << "." << std::endl;
466 req->addRequestRange( block._start, block._len, std::move(dig), block._checksum, {}, block._relevantDigestLen, block._chksumPad );
467 }
468 };
469
470 executeRequest ( req, &report );
471
472 //we might have the file ready
473 std::string err;
474 if ( !zyppng::ZckHelper::validateZckFile( target, err) ) {
475 ERR << "ZCK failed with error: " << err << std::endl;
476 return false;
477 }
478 return true;
479 }
480#endif
481 return false;
482 }
483
484
485
487
488 void MediaCurl2::getDir( const Pathname & dirname, bool recurse_r ) const
489 {
490 filesystem::DirContent content;
491 getDirInfo( content, dirname, /*dots*/false );
492
493 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
494 Pathname filename = dirname + it->name;
495 int res = 0;
496
497 switch ( it->type ) {
498 case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
499 case filesystem::FT_FILE:
500 getFile( OnMediaLocation( filename ) );
501 break;
502 case filesystem::FT_DIR: // newer directory.yast contain at least directory info
503 if ( recurse_r ) {
504 getDir( filename, recurse_r );
505 } else {
506 res = assert_dir( localPath( filename ) );
507 if ( res ) {
508 WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl;
509 }
510 }
511 break;
512 default:
513 // don't provide devices, sockets, etc.
514 break;
515 }
516 }
517 }
518
520
521 void MediaCurl2::getDirInfo( std::list<std::string> & retlist,
522 const Pathname & dirname, bool dots ) const
523 {
524 getDirectoryYast( retlist, dirname, dots );
525 }
526
528
529 void MediaCurl2::getDirInfo( filesystem::DirContent & retlist,
530 const Pathname & dirname, bool dots ) const
531 {
532 getDirectoryYast( retlist, dirname, dots );
533 }
534
535 void MediaCurl2::executeRequest( zyppng::NetworkRequestRef req , callback::SendReport<DownloadProgressReport> *report )
536 {
537 auto loop = zyppng::EventLoop::create();
538
539 _nwDispatcher->run();
540
541 bool firstAuth = true;
542 bool retry = true;
543 int maxTries = _effectiveSettings.maxSilentTries();
544
545 while ( retry ) {
546 std::optional<internal::ProgressTracker> progTracker;
547
548 std::vector<zyppng::connection> signalConnections {
549 req->sigStarted().connect( [&]( zyppng::NetworkRequest &req ){
550 if ( !report) return;
551 (*report)->start( req.url(), req.targetFilePath() );
552 }),
553 req->sigProgress().connect( [&]( zyppng::NetworkRequest &req, off_t dlTotal, off_t dlNow, off_t, off_t ){
554 if ( !report || !progTracker )
555 return;
556
557 progTracker->updateStats( dlTotal, dlNow );
558 if ( !(*report)->progress( progTracker->_dnlPercent, req.url(), progTracker-> _drateTotal, progTracker->_drateLast ) )
559 _nwDispatcher->cancel ( req );
560
561 }),
562 req->sigFinished().connect( [&]( zyppng::NetworkRequest &req, const zyppng::NetworkRequestError &err ) {
563 loop->quit();
564 })
565 };
566
567 // clean up slots for every loop
568 zypp_defer {
569 std::for_each( signalConnections.begin(), signalConnections.end(), []( auto &conn ) { conn.disconnect(); });
570 signalConnections.clear();
571 };
572
573 if ( report ) {
574 progTracker = internal::ProgressTracker();
575 }
576
577 maxTries--;
578 retry = false; // normally we don't retry
579 req->transferSettings() = _effectiveSettings; // use settings from MediaCurl
580 _nwDispatcher->enqueue ( req );
581 loop->run();
582
583 // once the request is done there should be nothing there anymore
584 if ( _nwDispatcher->count () != 0 ) {
585 ZYPP_THROW( zypp::Exception("Unexpected request count after finishing MediaCurl2 request!") );
586 }
587
588 if ( req->hasError() ) {
589 auto errCode = zypp::media::DownloadProgressReport::ERROR;
590 std::exception_ptr excp;
591 const auto &error = req->error();
592 switch ( error.type() ) {
593 case zyppng::NetworkRequestError::InternalError:
594 case zyppng::NetworkRequestError::InvalidChecksum:
595 case zyppng::NetworkRequestError::UnsupportedProtocol:
596 case zyppng::NetworkRequestError::MalformedURL:
597 case zyppng::NetworkRequestError::PeerCertificateInvalid:
598 case zyppng::NetworkRequestError::ConnectionFailed:
599 case zyppng::NetworkRequestError::ServerReturnedError:
600 case zyppng::NetworkRequestError::MissingData:
601 case zyppng::NetworkRequestError::RangeFail: {
602 excp = ZYPP_EXCPT_PTR( zypp::media::MediaCurlException( req->url(), error.toString(), error.nativeErrorString() ) );
603 break;
604 }
605 case zyppng::NetworkRequestError::Cancelled: {
606 excp = ZYPP_EXCPT_PTR( zypp::media::MediaRequestCancelledException( error.toString() ) );
607 break;
608 }
609 case zyppng::NetworkRequestError::ExceededMaxLen: {
610 excp = ZYPP_EXCPT_PTR( zypp::media::MediaFileSizeExceededException( req->url(), req->expectedFileSize() ) );
611 break;
612 }
613 case zyppng::NetworkRequestError::TemporaryProblem: {
614 excp = ZYPP_EXCPT_PTR( zypp::media::MediaTemporaryProblemException( req->url(), error.toString() ) );
615 break;
616 }
617 case zyppng::NetworkRequestError::Timeout: {
618 excp = ZYPP_EXCPT_PTR( zypp::media::MediaTimeoutException( req->url(), error.toString() ) );
619 break;
620 }
621 case zyppng::NetworkRequestError::Forbidden: {
622 excp = ZYPP_EXCPT_PTR( zypp::media::MediaForbiddenException( req->url(), error.toString() ) );
623 break;
624 }
625 case zyppng::NetworkRequestError::NotFound: {
626 errCode = zypp::media::DownloadProgressReport::NOT_FOUND;
627
628 //@BUG using getPathName() can result in wrong error messages
629 excp = ZYPP_EXCPT_PTR( zypp::media::MediaFileNotFoundException( _url, req->url().getPathName() ) );
630 break;
631 }
632 case zyppng::NetworkRequestError::Unauthorized:
633 case zyppng::NetworkRequestError::AuthFailed: {
634
635 //in case we got a auth hint from the server the error object will contain it
636 std::string authHint = error.extraInfoValue("authHint", std::string());
637 if ( authenticate( authHint, firstAuth ) ) {
638 firstAuth = false;
639 retry = true;
640 continue;
641 }
642
643 errCode = zypp::media::DownloadProgressReport::ACCESS_DENIED;
644 excp = ZYPP_EXCPT_PTR( zypp::media::MediaUnauthorizedException( req->url(), error.toString(), error.nativeErrorString(), "" ) );
645 break;
646 }
647 case zyppng::NetworkRequestError::NoError:
648 // should never happen
649 DBG << "BUG: Download error flag is set , but Error code is NoError" << std::endl;
650 break;
651 case zyppng::NetworkRequestError::Http2Error:
652 case zyppng::NetworkRequestError::Http2StreamError: {
653 excp = ZYPP_EXCPT_PTR( zypp::media::MediaCurlException( req->url(), error.toString(), error.nativeErrorString() ) );
654 break;
655 }
656 }
657
658 if ( excp ) {
659 if ( maxTries > 0 ) {
660 retry = true;
661 continue;
662 }
663
664 if ( report ) (*report)->finish( req->url(), errCode, error.toString() );
665 std::rethrow_exception( excp );
666 }
667 }
668
669 }
670
671 if ( report ) (*report)->finish( req->url(), zypp::media::DownloadProgressReport::NO_ERROR, "" );
672 }
673
674
675 bool MediaCurl2::authenticate(const std::string & availAuthTypes, bool firstTry)
676 {
678 CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot()));
679 return authenticate( _url, cm, _effectiveSettings, availAuthTypes, firstTry );
680 }
681
682 bool MediaCurl2::authenticate(const Url &url, CredentialManager &cm, TransferSettings &settings, const std::string & availAuthTypes, bool firstTry)
683 {
684 CurlAuthData_Ptr credentials;
685
686 // get stored credentials
687 AuthData_Ptr cmcred = cm.getCred(url);
688
689 if (cmcred && firstTry)
690 {
691 credentials.reset(new CurlAuthData(*cmcred));
692 DBG << "got stored credentials:" << endl << *credentials << endl;
693 }
694 // if not found, ask user
695 else
696 {
697
698 CurlAuthData_Ptr curlcred;
699 curlcred.reset(new CurlAuthData());
700 callback::SendReport<AuthenticationReport> auth_report;
701
702 // preset the username if present in current url
703 if (!url.getUsername().empty() && firstTry)
704 curlcred->setUsername(url.getUsername());
705 // if CM has found some credentials, preset the username from there
706 else if (cmcred)
707 curlcred->setUsername(cmcred->username());
708
709 // indicate we have no good credentials from CM
710 cmcred.reset();
711
712 std::string prompt_msg = str::Format(_("Authentication required for '%s'")) % url.asString();
713
714 // set available authentication types from the exception
715 // might be needed in prompt
716 curlcred->setAuthType(availAuthTypes);
717
718 // ask user
719 if (auth_report->prompt(url, prompt_msg, *curlcred))
720 {
721 DBG << "callback answer: retry" << endl
722 << "CurlAuthData: " << *curlcred << endl;
723
724 if (curlcred->valid())
725 {
726 credentials = curlcred;
727 // if (credentials->username() != _url.getUsername())
728 // _url.setUsername(credentials->username());
736 }
737 }
738 else
739 {
740 DBG << "callback answer: cancel" << endl;
741 }
742 }
743
744 // set username and password
745 if (credentials)
746 {
747 settings.setUsername(credentials->username());
748 settings.setPassword(credentials->password());
749
750 // set available authentication types from the exception
751 if (credentials->authType() == CURLAUTH_NONE)
752 credentials->setAuthType(availAuthTypes);
753
754 // set auth type (seems this must be set _after_ setting the userpwd)
755 if (credentials->authType() != CURLAUTH_NONE) {
756 settings.setAuthType(credentials->authTypeAsString());
757 }
758
759 if (!cmcred)
760 {
761 credentials->setUrl(url);
762 cm.addCred(*credentials);
763 cm.save();
764 }
765
766 return true;
767 }
768
769 return false;
770 }
771
772 } // namespace media
773} // namespace zypp
774//
DownloadProgressTracker.h
MediaCurl2.h
OptionalDownloadProgressReport.h
Target.h
ZConfig.h
ZYppFactory.h
ZYppImpl.h
zypp::Digest
Compute Message Digests (MD5, SHA1 etc)
Definition Digest.h:38
zypp::Digest::digestVectorToString
static std::string digestVectorToString(const UByteArray &vec)
get hex string representation of the digest vector given as parameter
Definition Digest.cc:243
zypp::Exception
Base class for Exception.
Definition Exception.h:147
zypp::Exception::asUserHistory
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:127
zypp::OnMediaLocation
Describes a resource file located on a medium.
Definition onmedialocation.h:37
zypp::OnMediaLocation::optional
bool optional() const
Whether this is an optional resource.
Definition onmedialocation.cc:109
zypp::OnMediaLocation::downloadSize
const ByteCount & downloadSize() const
The size of the resource on the server.
Definition onmedialocation.cc:115
zypp::OnMediaLocation::filename
const Pathname & filename() const
The path to the resource on the medium.
Definition onmedialocation.cc:88
zypp::OnMediaLocation::deltafile
const Pathname & deltafile() const
The existing deltafile that can be used to reduce download size ( zchunk or metalink )
Definition onmedialocation.cc:151
zypp::OnMediaLocation::headerSize
const ByteCount & headerSize() const
The size of the header prepending the resource (e.g.
Definition onmedialocation.cc:139
zypp::OnMediaLocation::headerChecksum
const CheckSum & headerChecksum() const
The checksum of the header prepending the resource (e.g.
Definition onmedialocation.cc:145
zypp::UByteArray
Definition ByteArray.h:46
zypp::Url
Url manipulation class.
Definition Url.h:93
zypp::Url::getScheme
std::string getScheme() const
Returns the scheme name of the URL.
Definition Url.cc:551
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:940
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::userMayRWX
bool userMayRWX() const
Definition PathInfo.h:361
zypp::filesystem::PathInfo::path
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
zypp::filesystem::PathInfo::isDir
bool isDir() const
Definition PathInfo.h:296
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:47
zypp::filesystem::Pathname::dirname
Pathname dirname() const
Return all but the last component od this path.
Definition Pathname.h:126
zypp::filesystem::Pathname::asString
const std::string & asString() const
String representation.
Definition Pathname.h:93
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition Pathname.h:116
zypp::filesystem::Pathname::absolutename
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Definition Pathname.h:141
zypp::media::CredentialManager
Definition credentialmanager.h:64
zypp::media::CredentialManager::save
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods.
Definition credentialmanager.cc:414
zypp::media::CredentialManager::getCred
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
Definition credentialmanager.cc:333
zypp::media::CredentialManager::addCred
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
Definition credentialmanager.cc:346
zypp::media::CurlAuthData
Curl HTTP authentication data.
Definition curlauthdata.h:22
zypp::media::MediaBadUrlEmptyHostException
Definition mediaexception.h:304
zypp::media::MediaBadUrlException
Definition mediaexception.h:288
zypp::media::MediaCurl2::releaseFrom
void releaseFrom(const std::string &ejectDev) override
Call concrete handler to release the media.
Definition MediaCurl2.cc:208
zypp::media::MediaCurl2::disconnectFrom
void disconnectFrom() override
Definition MediaCurl2.cc:200
zypp::media::MediaCurl2::tryZchunk
bool tryZchunk(zyppng::NetworkRequestRef req, const OnMediaLocation &srcFile, const Pathname &target, callback::SendReport< DownloadProgressReport > &report)
Definition MediaCurl2.cc:414
zypp::media::MediaCurl2::getFile
void getFile(const OnMediaLocation &file) const override
Call concrete handler to provide file below attach point.
Definition MediaCurl2.cc:215
zypp::media::MediaCurl2::getFileCopy
void getFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename) const override
Definition MediaCurl2.cc:224
zypp::media::MediaCurl2::getDir
void getDir(const Pathname &dirname, bool recurse_r) const override
Call concrete handler to provide directory content (not recursive!) below attach point.
Definition MediaCurl2.cc:488
zypp::media::MediaCurl2::attachTo
void attachTo(bool next=false) override
Call concrete handler to attach the media.
Definition MediaCurl2.cc:170
zypp::media::MediaCurl2::getDirInfo
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 MediaCurl2.cc:521
zypp::media::MediaCurl2::_evDispatcher
zyppng::EventDispatcherRef _evDispatcher
Definition MediaCurl2.h:131
zypp::media::MediaCurl2::getDoesFileExist
bool getDoesFileExist(const Pathname &filename) const override
Repeatedly calls doGetDoesFileExist() until it successfully returns, fails unexpectedly,...
Definition MediaCurl2.cc:258
zypp::media::MediaCurl2::OPTION_NO_IFMODSINCE
@ OPTION_NO_IFMODSINCE
to not add a IFMODSINCE header if target exists
Definition MediaCurl2.h:52
zypp::media::MediaCurl2::clearQueryString
Url clearQueryString(const Url &url) const
Definition MediaCurl2.cc:111
zypp::media::MediaCurl2::executeRequest
void executeRequest(zyppng::NetworkRequestRef req, callback::SendReport< DownloadProgressReport > *report=nullptr)
Definition MediaCurl2.cc:535
zypp::media::MediaCurl2::doGetFileCopy
virtual void doGetFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename, callback::SendReport< DownloadProgressReport > &_report, RequestOptions options=OPTION_NONE) const
Definition MediaCurl2.cc:302
zypp::media::MediaCurl2::checkProtocol
void checkProtocol(const Url &url) const
check the url is supported by the curl library
Definition MediaCurl2.cc:118
zypp::media::MediaCurl2::checkAttachPoint
bool checkAttachPoint(const Pathname &apoint) const override
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
Definition MediaCurl2.cc:195
zypp::media::MediaCurl2::setupEasy
void setupEasy()
initializes the curl easy handle with the data from the url
Definition MediaCurl2.cc:129
zypp::media::MediaCurl2::_nwDispatcher
zyppng::NetworkRequestDispatcherRef _nwDispatcher
Definition MediaCurl2.h:132
zypp::media::MediaCurl2::_effectiveSettings
TransferSettings _effectiveSettings
Definition MediaCurl2.h:133
zypp::media::MediaCurl2::MediaCurl2
MediaCurl2(const Url &url_r, const Pathname &attach_point_hint_r)
Definition MediaCurl2.cc:75
zypp::media::MediaCurl2::authenticate
static bool authenticate(const Url &url, CredentialManager &cm, TransferSettings &settings, const std::string &availAuthTypes, bool firstTry)
Definition MediaCurl2.cc:682
zypp::media::MediaCurlException
Definition mediaexception.h:361
zypp::media::MediaException
Just inherits Exception to separate media exceptions.
Definition mediaexception.h:37
zypp::media::MediaFileNotFoundException
Definition mediaexception.h:164
zypp::media::MediaFileSizeExceededException
Definition mediaexception.h:509
zypp::media::MediaForbiddenException
Definition mediaexception.h:481
zypp::media::MediaHandler::isUseableAttachPoint
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...
Definition MediaHandler.cc:416
zypp::media::MediaHandler::url
Url url() const
Url used.
Definition MediaHandler.h:503
zypp::media::MediaHandler::checkAttachPoint
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
Definition MediaHandler.cc:848
zypp::media::MediaHandler::disconnect
void disconnect()
Use concrete handler to isconnect media.
Definition MediaHandler.cc:687
zypp::media::MediaHandler::createAttachPoint
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
Definition MediaHandler.cc:312
zypp::media::MediaHandler::setMediaSource
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
Definition MediaHandler.cc:432
zypp::media::MediaHandler::localPath
Pathname localPath(const Pathname &pathname) const
Files provided will be available at 'localPath(filename)'.
Definition MediaHandler.cc:664
zypp::media::MediaHandler::_url
const Url _url
Url to handle.
Definition MediaHandler.h:113
zypp::media::MediaHandler::getDirectoryYast
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
Definition MediaHandler.cc:1114
zypp::media::MediaHandler::setAttachPoint
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
Definition MediaHandler.cc:200
zypp::media::MediaHandler::attachPoint
Pathname attachPoint() const
Return the currently used attach point.
Definition MediaHandler.cc:185
zypp::media::MediaNetworkCommonHandler::getFileUrl
Url getFileUrl(const Pathname &filename) const
concatenate the attach url and the filename to a complete download url
Definition MediaNetworkCommonHandler.cc:105
zypp::media::MediaNetworkCommonHandler::anonymousIdHeader
static const char * anonymousIdHeader()
Definition MediaNetworkCommonHandler.cc:77
zypp::media::MediaNetworkCommonHandler::distributionFlavorHeader
static const char * distributionFlavorHeader()
Definition MediaNetworkCommonHandler.cc:91
zypp::media::MediaNetworkCommonHandler::MediaNetworkCommonHandler
MediaNetworkCommonHandler(const Url &url_r, const Pathname &attach_point_r, const Pathname &urlpath_below_attachpoint_r, const bool does_download_r)
Definition MediaNetworkCommonHandler.h:33
zypp::media::MediaNetworkCommonHandler::_settings
TransferSettings _settings
Definition MediaNetworkCommonHandler.h:69
zypp::media::MediaNetworkCommonHandler::agentString
static const char * agentString()
Definition MediaNetworkCommonHandler.cc:121
zypp::media::MediaNetworkCommonHandler::settings
TransferSettings & settings()
Definition MediaNetworkCommonHandler.h:43
zypp::media::MediaNotAFileException
Definition mediaexception.h:254
zypp::media::MediaNotSupportedException
Definition mediaexception.h:348
zypp::media::MediaRequestCancelledException
Definition mediaexception.h:564
zypp::media::MediaSource
Media source internally used by MediaManager and MediaHandler.
Definition MediaSource.h:38
zypp::media::MediaSystemException
Definition mediaexception.h:237
zypp::media::MediaTemporaryProblemException
For HTTP 503 and similar.
Definition mediaexception.h:527
zypp::media::MediaTimeoutException
Definition mediaexception.h:495
zypp::media::MediaUnauthorizedException
Definition mediaexception.h:446
zypp::media::MediaWriteException
Definition mediaexception.h:181
zypp::media::TransferSettings
Holds transfer setting.
Definition transfersettings.h:34
zyppng::EventLoop::create
static Ptr create()
Definition eventloop_glib.cc:24
zyppng::NetworkRequestError
The NetworkRequestError class Represents a error that occured in.
Definition networkrequesterror.h:24
zyppng::NetworkRequestError::ServerReturnedError
@ ServerReturnedError
Definition networkrequesterror.h:42
zyppng::NetworkRequestError::Forbidden
@ Forbidden
Definition networkrequesterror.h:38
zyppng::NetworkRequestError::PeerCertificateInvalid
@ PeerCertificateInvalid
Definition networkrequesterror.h:30
zyppng::NetworkRequestError::UnsupportedProtocol
@ UnsupportedProtocol
Definition networkrequesterror.h:34
zyppng::NetworkRequestError::InternalError
@ InternalError
Definition networkrequesterror.h:28
zyppng::NetworkRequestError::ExceededMaxLen
@ ExceededMaxLen
Definition networkrequesterror.h:32
zyppng::NetworkRequestError::Unauthorized
@ Unauthorized
Definition networkrequesterror.h:40
zyppng::NetworkRequestError::MalformedURL
@ MalformedURL
Definition networkrequesterror.h:35
zyppng::NetworkRequestError::ConnectionFailed
@ ConnectionFailed
Definition networkrequesterror.h:31
zyppng::NetworkRequestError::RangeFail
@ RangeFail
Definition networkrequesterror.h:44
zyppng::NetworkRequestError::AuthFailed
@ AuthFailed
Definition networkrequesterror.h:41
zyppng::NetworkRequestError::Timeout
@ Timeout
Definition networkrequesterror.h:37
zyppng::NetworkRequestError::Http2Error
@ Http2Error
Definition networkrequesterror.h:45
zyppng::NetworkRequestError::MissingData
@ MissingData
Definition networkrequesterror.h:43
zyppng::NetworkRequestError::NoError
@ NoError
Definition networkrequesterror.h:27
zyppng::NetworkRequestError::NotFound
@ NotFound
Definition networkrequesterror.h:39
zyppng::NetworkRequestError::Cancelled
@ Cancelled
Definition networkrequesterror.h:29
zyppng::NetworkRequestError::Http2StreamError
@ Http2StreamError
Definition networkrequesterror.h:46
zyppng::NetworkRequestError::TemporaryProblem
@ TemporaryProblem
Definition networkrequesterror.h:36
zyppng::NetworkRequestError::InvalidChecksum
@ InvalidChecksum
Definition networkrequesterror.h:33
zyppng::NetworkRequest
Definition request.h:43
zyppng::NetworkRequest::targetFilePath
const zypp::Pathname & targetFilePath() const
Returns the target filename path.
Definition request.cc:919
zyppng::NetworkRequest::HeadRequest
@ HeadRequest
Definition request.h:71
zyppng::NetworkRequest::url
Url url() const
Definition request.cc:905
zyppng::NetworkRequest::sigFinished
SignalProxy< void(NetworkRequest &req, const NetworkRequestError &err)> sigFinished()
Signals that the download finished.
Definition request.cc:1066
zyppng::NetworkRequest::WriteShared
@ WriteShared
Definition request.h:66
zyppng::NetworkRequest::sigProgress
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.
Definition request.cc:1061
zyppng::ZckHelper::validateZckFile
static bool validateZckFile(const zypp::Pathname &file, std::string &error)
Definition zckhelper.cc:169
zyppng::ZckHelper::isZchunkFile
static bool isZchunkFile(const zypp::Pathname &file)
Definition zckhelper.cc:21
zyppng::ZckHelper::prepareZck
static PrepareResult prepareZck(const zypp::Pathname &delta, const zypp::Pathname &target, const zypp::ByteCount &expectedFileSize)
Definition zckhelper.cc:34
curlhelper_p.h
eventloop.h
linuxhelpers_p.h
mediadebug_p.h
WAR_MEDIA
#define WAR_MEDIA
Definition mediadebug_p.h:30
DBG_MEDIA
#define DBG_MEDIA
Definition mediadebug_p.h:28
internal
Definition OptionalDownloadProgressReport.cc:12
internal::fillSettingsFromUrl
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:183
internal::fillSettingsSystemProxy
void fillSettingsSystemProxy(const Url &url, media::TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Definition curlhelper.cc:338
std
Definition Arch.h:364
zypp::base
Definition Random.cc:7
zypp::env::ZYPP_MEDIA_CURL_DEBUG
const long & ZYPP_MEDIA_CURL_DEBUG()
const long& for setting CURLOPT_DEBUGDATA Returns a reference to a static variable,...
Definition curlhelper.cc:36
zypp::filesystem::FT_DIR
@ FT_DIR
Definition PathInfo.h:64
zypp::filesystem::FT_NOT_AVAIL
@ FT_NOT_AVAIL
Definition PathInfo.h:61
zypp::filesystem::FT_FILE
@ FT_FILE
Definition PathInfo.h:63
zypp::filesystem::applyUmaskTo
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition PathInfo.h:805
zypp::filesystem::DirContent
std::list< DirEntry > DirContent
Returned by readdir.
Definition PathInfo.h:526
zypp::filesystem::unlink
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
zypp::media
Definition MediaCD.cc:47
zypp::media::AuthData_Ptr
shared_ptr< AuthData > AuthData_Ptr
Definition authdata.h:81
zypp::media::MediaSourceRef
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition MediaSource.h:125
zypp::media::CurlAuthData_Ptr
shared_ptr< CurlAuthData > CurlAuthData_Ptr
Definition curlauthdata.h:102
zypp::str::asString
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
Definition String.h:139
zypp::target
Definition KeyRing.h:325
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition Application.cc:20
zypp::ManagedFile
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
zyppng
Definition MediaCurl2.h:22
networkrequestdispatcher.h
request.h
internal::OptionalDownloadProgressReport
Bottleneck filtering all DownloadProgressReport issued from Media[Muli]Curl.
Definition OptionalDownloadProgressReport.h:22
zypp::AutoFD
AutoDispose<int> calling ::close
Definition AutoDispose.h:310
zypp::AutoFREE
Definition AutoDispose.h:332
zypp::callback::SendReport
Definition Callback.h:237
zypp::internal::ProgressTracker
Definition DownloadProgressTracker.h:17
zypp::media::CredManagerOptions
Definition credentialmanager.h:40
zypp::media::DownloadProgressReport::Error
Error
Definition ZYppCallbacks.h:370
zypp::media::DownloadProgressReport::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:371
zypp::media::DownloadProgressReport::ACCESS_DENIED
@ ACCESS_DENIED
Definition ZYppCallbacks.h:374
zypp::media::DownloadProgressReport::ERROR
@ ERROR
Definition ZYppCallbacks.h:375
zypp::media::DownloadProgressReport::NOT_FOUND
@ NOT_FOUND
Definition ZYppCallbacks.h:372
zypp::str::Format
Convenient building of std::string with boost::format.
Definition String.h:253
zyppng::ZckHelper::PrepareResult::NothingToDo
@ NothingToDo
Definition zckhelper.h:30
zyppng::ZckHelper::PrepareResult::Error
@ Error
Definition zckhelper.h:29
zyppng::ZckHelper::PrepareResult::Success
@ Success
Definition zckhelper.h:32
zyppng::ZckHelper::PrepareResult::ExceedsMaxLen
@ ExceedsMaxLen
Definition zckhelper.h:31
threaddata_p.h
userrequestexception.h
zckhelper.h
zypp_defer
#define zypp_defer
Definition AutoDispose.h:293
ZYPP_RETHROW
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:444
ZYPP_EXCPT_PTR
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:428
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:424
_
#define _(MSG)
Definition Gettext.h:39
DBG
#define DBG
Definition Logger.h:99
MIL
#define MIL
Definition Logger.h:100
ERR
#define ERR
Definition Logger.h:102
WAR
#define WAR
Definition Logger.h:101
ExternalProgram.h
Gettext.h
Interface to gettext.
Logger.h
String.h