00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <iostream>
00014
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/ExternalProgram.h"
00017 #include "zypp/base/String.h"
00018
00019 #include "zypp/media/MediaCurl.h"
00020 #include "zypp/media/proxyinfo/ProxyInfos.h"
00021 #include "zypp/media/ProxyInfo.h"
00022 #include "zypp/thread/Once.h"
00023 #include <cstdlib>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <sys/mount.h>
00027 #include <errno.h>
00028 #include <dirent.h>
00029 #include <unistd.h>
00030
00031 #include "config.h"
00032
00033 #define DETECT_DIR_INDEX 0
00034
00035 using namespace std;
00036 using namespace zypp::base;
00037
00038 namespace
00039 {
00040 zypp::thread::OnceFlag g_InitOnceFlag = PTHREAD_ONCE_INIT;
00041 zypp::thread::OnceFlag g_FreeOnceFlag = PTHREAD_ONCE_INIT;
00042
00043 extern "C" void _do_free_once()
00044 {
00045 curl_global_cleanup();
00046 }
00047
00048 extern "C" void globalFreeOnce()
00049 {
00050 zypp::thread::callOnce(g_FreeOnceFlag, _do_free_once);
00051 }
00052
00053 extern "C" void _do_init_once()
00054 {
00055 CURLcode ret = curl_global_init( CURL_GLOBAL_ALL );
00056 if ( ret != 0 )
00057 {
00058 WAR << "curl global init failed" << endl;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 }
00070
00071 inline void globalInitOnce()
00072 {
00073 zypp::thread::callOnce(g_InitOnceFlag, _do_init_once);
00074 }
00075 }
00076
00077 namespace zypp {
00078 namespace media {
00079
00080 Pathname MediaCurl::_cookieFile = "/var/lib/YaST2/cookies";
00081 std::string MediaCurl::_agent = "Novell ZYPP Installer";
00082
00084
00085 static inline void escape( string & str_r,
00086 const char char_r, const string & escaped_r ) {
00087 for ( string::size_type pos = str_r.find( char_r );
00088 pos != string::npos; pos = str_r.find( char_r, pos ) ) {
00089 str_r.replace( pos, 1, escaped_r );
00090 }
00091 }
00092
00093 static inline string escapedPath( string path_r ) {
00094 escape( path_r, ' ', "%20" );
00095 return path_r;
00096 }
00097
00098 static inline string unEscape( string text_r ) {
00099 char * tmp = curl_unescape( text_r.c_str(), 0 );
00100 string ret( tmp );
00101 curl_free( tmp );
00102 return ret;
00103 }
00104
00106
00107
00108
00110
00111 MediaCurl::MediaCurl( const Url & url_r,
00112 const Pathname & attach_point_hint_r )
00113 : MediaHandler( url_r, attach_point_hint_r,
00114 "/",
00115 true ),
00116 _curl( NULL )
00117 {
00118 _curlError[0] = '\0';
00119
00120 MIL << "MediaCurl::MediaCurl(" << url_r << ", " << attach_point_hint_r << ")" << endl;
00121
00122 globalInitOnce();
00123
00124 if( !attachPoint().empty())
00125 {
00126 PathInfo ainfo(attachPoint());
00127 Pathname apath(attachPoint() + "XXXXXX");
00128 char *atemp = ::strdup( apath.asString().c_str());
00129 char *atest = NULL;
00130 if( !ainfo.isDir() || !ainfo.userMayRWX() ||
00131 atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
00132 {
00133 WAR << "attach point " << ainfo.path()
00134 << " is not useable for " << url_r.getScheme() << endl;
00135 setAttachPoint("", true);
00136 }
00137 else if( atest != NULL)
00138 ::rmdir(atest);
00139
00140 if( atemp != NULL)
00141 ::free(atemp);
00142 }
00143 }
00144
00145 void MediaCurl::setCookieFile( const Pathname &fileName )
00146 {
00147 _cookieFile = fileName;
00148 }
00149
00151
00152
00153
00154
00155
00156
00157
00158 void MediaCurl::attachTo (bool next)
00159 {
00160 if ( next )
00161 ZYPP_THROW(MediaNotSupportedException(_url));
00162
00163 if ( !_url.isValid() )
00164 ZYPP_THROW(MediaBadUrlException(_url));
00165
00166 curl_version_info_data *curl_info = NULL;
00167 curl_info = curl_version_info(CURLVERSION_NOW);
00168
00169 if (curl_info->protocols)
00170 {
00171 const char * const *proto;
00172 std::string scheme( _url.getScheme());
00173 bool found = false;
00174 for(proto=curl_info->protocols; !found && *proto; ++proto)
00175 {
00176 if( scheme == std::string((const char *)*proto))
00177 found = true;
00178 }
00179 if( !found)
00180 {
00181 std::string msg("Unsupported protocol '");
00182 msg += scheme;
00183 msg += "'";
00184 ZYPP_THROW(MediaBadUrlException(_url, msg));
00185 }
00186 }
00187
00188 if( !isUseableAttachPoint(attachPoint()))
00189 {
00190 std::string mountpoint = createAttachPoint().asString();
00191
00192 if( mountpoint.empty())
00193 ZYPP_THROW( MediaBadAttachPointException(url()));
00194
00195 setAttachPoint( mountpoint, true);
00196 }
00197
00198 disconnectFrom();
00199 _curl = curl_easy_init();
00200 if ( !_curl ) {
00201 ZYPP_THROW(MediaCurlInitException(_url));
00202 }
00203
00204 CURLcode ret = curl_easy_setopt( _curl, CURLOPT_ERRORBUFFER, _curlError );
00205 if ( ret != 0 ) {
00206 disconnectFrom();
00207 ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer"));
00208 }
00209
00210 ret = curl_easy_setopt( _curl, CURLOPT_FAILONERROR, true );
00211 if ( ret != 0 ) {
00212 disconnectFrom();
00213 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00214 }
00215
00216 ret = curl_easy_setopt( _curl, CURLOPT_NOSIGNAL, 1 );
00217 if ( ret != 0 ) {
00218 disconnectFrom();
00219 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 ret = curl_easy_setopt( _curl, CURLOPT_CONNECTTIMEOUT, 60);
00243 if ( ret != 0 ) {
00244 disconnectFrom();
00245 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00246 }
00247
00248 if ( _url.getScheme() == "http" ) {
00249
00250
00251 ret = curl_easy_setopt ( _curl, CURLOPT_FOLLOWLOCATION, true );
00252 if ( ret != 0) {
00253 disconnectFrom();
00254 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00255 }
00256 ret = curl_easy_setopt ( _curl, CURLOPT_MAXREDIRS, 3L );
00257 if ( ret != 0) {
00258 disconnectFrom();
00259 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00260 }
00261 ret = curl_easy_setopt ( _curl, CURLOPT_USERAGENT, _agent.c_str() );
00262 if ( ret != 0) {
00263 disconnectFrom();
00264 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00265 }
00266 }
00267
00268 if ( _url.getScheme() == "https" ) {
00269 ret = curl_easy_setopt( _curl, CURLOPT_SSL_VERIFYPEER, 1 );
00270 if ( ret != 0 ) {
00271 disconnectFrom();
00272 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00273 }
00274 ret = curl_easy_setopt( _curl, CURLOPT_CAPATH, "/etc/ssl/certs/" );
00275 if ( ret != 0 ) {
00276 disconnectFrom();
00277 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00278 }
00279 ret = curl_easy_setopt( _curl, CURLOPT_SSL_VERIFYHOST, 2 );
00280 if ( ret != 0 ) {
00281 disconnectFrom();
00282 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00283 }
00284 ret = curl_easy_setopt ( _curl, CURLOPT_USERAGENT, _agent.c_str() );
00285 if ( ret != 0) {
00286 disconnectFrom();
00287 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 if ( _url.getUsername().empty() ) {
00300 if ( _url.getScheme() == "ftp" ) {
00301 string id = "yast2@";
00302 id += VERSION;
00303 DBG << "Anonymous FTP identification: '" << id << "'" << endl;
00304 _userpwd = "anonymous:" + id;
00305 }
00306 } else {
00307 _userpwd = _url.getUsername();
00308 if ( _url.getPassword().size() ) {
00309 _userpwd += ":" + _url.getPassword();
00310 }
00311 }
00312
00313 if ( _userpwd.size() ) {
00314 _userpwd = unEscape( _userpwd );
00315 ret = curl_easy_setopt( _curl, CURLOPT_USERPWD, _userpwd.c_str() );
00316 if ( ret != 0 ) {
00317 disconnectFrom();
00318 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00319 }
00320
00321 if( !_url.getQueryParam("auth").empty() &&
00322 (_url.getScheme() == "http" || _url.getScheme() == "https"))
00323 {
00324 std::vector<std::string> list;
00325 std::vector<std::string>::const_iterator it;
00326 str::split(_url.getQueryParam("auth"), std::back_inserter(list), ",");
00327
00328 long auth = CURLAUTH_NONE;
00329 for(it = list.begin(); it != list.end(); ++it)
00330 {
00331 if(*it == "basic")
00332 {
00333 auth |= CURLAUTH_BASIC;
00334 }
00335 else
00336 if(*it == "digest")
00337 {
00338 auth |= CURLAUTH_DIGEST;
00339 }
00340 else
00341 if((curl_info && (curl_info->features & CURL_VERSION_NTLM)) &&
00342 (*it == "ntlm"))
00343 {
00344 auth |= CURLAUTH_NTLM;
00345 }
00346 else
00347 if((curl_info && (curl_info->features & CURL_VERSION_SPNEGO)) &&
00348 (*it == "spnego" || *it == "negotiate"))
00349 {
00350
00351 auth |= CURLAUTH_GSSNEGOTIATE;
00352 }
00353 else
00354 if((curl_info && (curl_info->features & CURL_VERSION_GSSNEGOTIATE)) &&
00355 (*it == "gssnego" || *it == "negotiate"))
00356 {
00357 auth |= CURLAUTH_GSSNEGOTIATE;
00358 }
00359 else
00360 {
00361 std::string msg("Unsupported HTTP authentication method '");
00362 msg += *it;
00363 msg += "'";
00364 disconnectFrom();
00365 ZYPP_THROW(MediaBadUrlException(_url, msg));
00366 }
00367 }
00368
00369 if( auth != CURLAUTH_NONE)
00370 {
00371 DBG << "Enabling HTTP authentication methods: "
00372 << _url.getQueryParam("auth") << std::endl;
00373
00374 ret = curl_easy_setopt( _curl, CURLOPT_HTTPAUTH, auth);
00375 if ( ret != 0 ) {
00376 disconnectFrom();
00377 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00378 }
00379 }
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390 _proxy = _url.getQueryParam( "proxy" );
00391
00392 if ( ! _proxy.empty() ) {
00393 string proxyport( _url.getQueryParam( "proxyport" ) );
00394 if ( ! proxyport.empty() ) {
00395 _proxy += ":" + proxyport;
00396 }
00397 } else {
00398
00399 ProxyInfo proxy_info (ProxyInfo::ImplPtr(new ProxyInfoSysconfig("proxy")));
00400
00401 if ( proxy_info.enabled())
00402 {
00403 bool useproxy = true;
00404
00405 std::list<std::string> nope = proxy_info.noProxy();
00406 for (ProxyInfo::NoProxyIterator it = proxy_info.noProxyBegin();
00407 it != proxy_info.noProxyEnd();
00408 it++)
00409 {
00410 std::string host( str::toLower(_url.getHost()));
00411 std::string temp( str::toLower(*it));
00412
00413
00414
00415
00416 if( temp.size() > 1 && temp.at(0) == '.')
00417 {
00418 if(host.size() > temp.size() &&
00419 host.compare(host.size() - temp.size(), temp.size(), temp) == 0)
00420 {
00421 DBG << "NO_PROXY: '" << *it << "' matches host '"
00422 << host << "'" << endl;
00423 useproxy = false;
00424 break;
00425 }
00426 }
00427 else
00428
00429 if( host == temp)
00430 {
00431 DBG << "NO_PROXY: '" << *it << "' matches host '"
00432 << host << "'" << endl;
00433 useproxy = false;
00434 break;
00435 }
00436 }
00437
00438 if ( useproxy ) {
00439 _proxy = proxy_info.proxy(_url.getScheme());
00440 }
00441 }
00442 }
00443
00444
00445 DBG << "Proxy: " << (_proxy.empty() ? "-none-" : _proxy) << endl;
00446
00447 if ( ! _proxy.empty() ) {
00448
00449 ret = curl_easy_setopt( _curl, CURLOPT_PROXY, _proxy.c_str() );
00450 if ( ret != 0 ) {
00451 disconnectFrom();
00452 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462 _proxyuserpwd = _url.getQueryParam( "proxyuser" );
00463
00464 if ( ! _proxyuserpwd.empty() ) {
00465
00466 string proxypassword( _url.getQueryParam( "proxypassword" ) );
00467 if ( ! proxypassword.empty() ) {
00468 _proxyuserpwd += ":" + proxypassword;
00469 }
00470
00471 } else {
00472 char *home = getenv("HOME");
00473 if( home && *home)
00474 {
00475 Pathname curlrcFile = string( home ) + string( "/.curlrc" );
00476
00477 PathInfo h_info(string(home), PathInfo::LSTAT);
00478 PathInfo c_info(curlrcFile, PathInfo::LSTAT);
00479
00480 if( h_info.isDir() && h_info.owner() == getuid() &&
00481 c_info.isFile() && c_info.owner() == getuid())
00482 {
00483 map<string,string> rc_data = proxyinfo::sysconfigRead(curlrcFile);
00484
00485 map<string,string>::const_iterator it = rc_data.find("proxy-user");
00486 if (it != rc_data.end())
00487 _proxyuserpwd = it->second;
00488 }
00489 else
00490 {
00491 WAR << "Not allowed to parse '" << curlrcFile
00492 << "': bad file owner" << std::endl;
00493 }
00494 }
00495 }
00496
00497 _proxyuserpwd = unEscape( _proxyuserpwd );
00498 ret = curl_easy_setopt( _curl, CURLOPT_PROXYUSERPWD, _proxyuserpwd.c_str() );
00499 if ( ret != 0 ) {
00500 disconnectFrom();
00501 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00502 }
00503 }
00504
00505
00506
00507
00508 _currentCookieFile = _cookieFile.asString();
00509
00510 ret = curl_easy_setopt( _curl, CURLOPT_COOKIEFILE,
00511 _currentCookieFile.c_str() );
00512 if ( ret != 0 ) {
00513 disconnectFrom();
00514 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00515 }
00516
00517 ret = curl_easy_setopt( _curl, CURLOPT_COOKIEJAR,
00518 _currentCookieFile.c_str() );
00519 if ( ret != 0 ) {
00520 disconnectFrom();
00521 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00522 }
00523
00524 ret = curl_easy_setopt( _curl, CURLOPT_PROGRESSFUNCTION,
00525 &progressCallback );
00526 if ( ret != 0 ) {
00527 disconnectFrom();
00528 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00529 }
00530
00531 ret = curl_easy_setopt( _curl, CURLOPT_NOPROGRESS, false );
00532 if ( ret != 0 ) {
00533 disconnectFrom();
00534 ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
00535 }
00536
00537
00538 MediaSourceRef media( new MediaSource(_url.getScheme(), _url.asString()));
00539 setMediaSource(media);
00540 }
00541
00542 bool
00543 MediaCurl::checkAttachPoint(const Pathname &apoint) const
00544 {
00545 return MediaHandler::checkAttachPoint( apoint, true, true);
00546 }
00547
00549
00550
00551
00552
00553
00554 void MediaCurl::disconnectFrom()
00555 {
00556 if ( _curl )
00557 {
00558 curl_easy_cleanup( _curl );
00559 _curl = NULL;
00560 }
00561 }
00562
00564
00565
00566
00567
00568
00569
00570
00571 void MediaCurl::releaseFrom( bool eject )
00572 {
00573 disconnect();
00574 }
00575
00576
00578
00579
00580
00581
00582
00583 void MediaCurl::getFile( const Pathname & filename ) const
00584 {
00585
00586
00587 getFileCopy(filename, localPath(filename).absolutename());
00588 }
00589
00590
00591 void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target) const
00592 {
00593 callback::SendReport<DownloadProgressReport> report;
00594
00595 Url url( _url );
00596
00597 try {
00598 doGetFileCopy(filename, target, report);
00599 }
00600 catch (MediaException & excpt_r)
00601 {
00602
00603
00604 report->finish(url, zypp::media::DownloadProgressReport::NOT_FOUND, excpt_r.msg());
00605 ZYPP_RETHROW(excpt_r);
00606 }
00607 report->finish(url, zypp::media::DownloadProgressReport::NO_ERROR, "");
00608 }
00609
00610 void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report) const
00611 {
00612 DBG << filename.asString() << endl;
00613
00614 if(!_url.isValid())
00615 ZYPP_THROW(MediaBadUrlException(_url));
00616
00617 if(_url.getHost().empty())
00618 ZYPP_THROW(MediaBadUrlEmptyHostException(_url));
00619
00620 string path = _url.getPathName();
00621 if ( !path.empty() && path != "/" && *path.rbegin() == '/' &&
00622 filename.absolute() ) {
00623
00624
00625 path += filename.asString().substr( 1, filename.asString().size() - 1 );
00626 } else if ( filename.relative() ) {
00627
00628 if ( !path.empty() && *path.rbegin() != '/' ) path += "/";
00629
00630 path += filename.asString().substr( 2, filename.asString().size() - 2 );
00631 } else {
00632 path += filename.asString();
00633 }
00634
00635 Url url( _url );
00636 url.setPathName( path );
00637
00638 Pathname dest = target.absolutename();
00639 if( assert_dir( dest.dirname() ) )
00640 {
00641 DBG << "assert_dir " << dest.dirname() << " failed" << endl;
00642 ZYPP_THROW( MediaSystemException(url, "System error on " + dest.dirname().asString()) );
00643 }
00644
00645 DBG << "URL: " << url.asString() << endl;
00646
00647
00648
00649
00650 Url curlUrl( url );
00651
00652
00653 curlUrl.setUsername( "" );
00654 curlUrl.setPassword( "" );
00655 curlUrl.setPathParams( "" );
00656 curlUrl.setQueryString( "" );
00657 curlUrl.setFragment( "" );
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 string urlBuffer( curlUrl.asString());
00668 CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL,
00669 urlBuffer.c_str() );
00670 if ( ret != 0 ) {
00671 ZYPP_THROW(MediaCurlSetOptException(url, _curlError));
00672 }
00673
00674 string destNew = target.asString() + ".new.zypp.XXXXXX";
00675 char *buf = ::strdup( destNew.c_str());
00676 if( !buf)
00677 {
00678 ERR << "out of memory for temp file name" << endl;
00679 ZYPP_THROW(MediaSystemException(
00680 url, "out of memory for temp file name"
00681 ));
00682 }
00683
00684 int tmp_fd = ::mkstemp( buf );
00685 if( tmp_fd == -1)
00686 {
00687 free( buf);
00688 ERR << "mkstemp failed for file '" << destNew << "'" << endl;
00689 ZYPP_THROW(MediaWriteException(destNew));
00690 }
00691 destNew = buf;
00692 free( buf);
00693
00694 FILE *file = ::fdopen( tmp_fd, "w" );
00695 if ( !file ) {
00696 ::close( tmp_fd);
00697 filesystem::unlink( destNew );
00698 ERR << "fopen failed for file '" << destNew << "'" << endl;
00699 ZYPP_THROW(MediaWriteException(destNew));
00700 }
00701
00702 DBG << "dest: " << dest << endl;
00703 DBG << "temp: " << destNew << endl;
00704
00705 ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, file );
00706 if ( ret != 0 ) {
00707 ::fclose( file );
00708 filesystem::unlink( destNew );
00709 ZYPP_THROW(MediaCurlSetOptException(url, _curlError));
00710 }
00711
00712
00713 report->start(url, dest);
00714 if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &report ) != 0 ) {
00715 WAR << "Can't set CURLOPT_PROGRESSDATA: " << _curlError << endl;;
00716 }
00717
00718 ret = curl_easy_perform( _curl );
00719
00720 if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, NULL ) != 0 ) {
00721 WAR << "Can't unset CURLOPT_PROGRESSDATA: " << _curlError << endl;;
00722 }
00723
00724 if ( ret != 0 ) {
00725 ::fclose( file );
00726 filesystem::unlink( destNew );
00727 ERR << "curl error: " << ret << ": " << _curlError << endl;
00728 std::string err;
00729 try {
00730 bool err_file_not_found = false;
00731 switch ( ret ) {
00732 case CURLE_UNSUPPORTED_PROTOCOL:
00733 case CURLE_URL_MALFORMAT:
00734 case CURLE_URL_MALFORMAT_USER:
00735 err = " Bad URL";
00736 case CURLE_HTTP_RETURNED_ERROR:
00737 {
00738 long httpReturnCode = 0;
00739 CURLcode infoRet = curl_easy_getinfo( _curl,
00740 CURLINFO_RESPONSE_CODE,
00741 &httpReturnCode );
00742 if ( infoRet == CURLE_OK ) {
00743 string msg = "HTTP response: " +
00744 str::numstring( httpReturnCode );
00745 if ( httpReturnCode == 401 )
00746 {
00747 err = " Login failed";
00748 }
00749 else
00750 if ( httpReturnCode == 404)
00751 {
00752 ZYPP_THROW(MediaFileNotFoundException(_url, filename));
00753 }
00754
00755 msg += err;
00756 DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
00757 ZYPP_THROW(MediaCurlException(url, msg, _curlError));
00758 }
00759 else
00760 {
00761 string msg = "Unable to retrieve HTTP response:";
00762 msg += err;
00763 DBG << msg << " (URL: " << url.asString() << ")" << std::endl;
00764 ZYPP_THROW(MediaCurlException(url, msg, _curlError));
00765 }
00766 }
00767 break;
00768 case CURLE_FTP_COULDNT_RETR_FILE:
00769 case CURLE_FTP_ACCESS_DENIED:
00770 err = "File not found";
00771 err_file_not_found = true;
00772 break;
00773 case CURLE_BAD_PASSWORD_ENTERED:
00774 case CURLE_FTP_USER_PASSWORD_INCORRECT:
00775 err = "Login failed";
00776 break;
00777 case CURLE_COULDNT_RESOLVE_PROXY:
00778 case CURLE_COULDNT_RESOLVE_HOST:
00779 case CURLE_COULDNT_CONNECT:
00780 case CURLE_FTP_CANT_GET_HOST:
00781 err = "Connection failed";
00782 break;
00783 case CURLE_WRITE_ERROR:
00784 err = "Write error";
00785 break;
00786 case CURLE_ABORTED_BY_CALLBACK:
00787 err = "User abort";
00788 break;
00789 case CURLE_SSL_PEER_CERTIFICATE:
00790 default:
00791 err = "Unrecognized error";
00792 break;
00793 }
00794 if( err_file_not_found)
00795 {
00796 ZYPP_THROW(MediaFileNotFoundException(_url, filename));
00797 }
00798 else
00799 {
00800 ZYPP_THROW(MediaCurlException(url, err, _curlError));
00801 }
00802 }
00803 catch (const MediaException & excpt_r)
00804 {
00805 ZYPP_RETHROW(excpt_r);
00806 }
00807 }
00808 #if DETECT_DIR_INDEX
00809 else
00810 if(curlUrl.getScheme() == "http" ||
00811 curlUrl.getScheme() == "https")
00812 {
00813
00814
00815
00816
00817
00818
00819
00820
00821 bool not_a_file = false;
00822 char *ptr = NULL;
00823 CURLcode ret = curl_easy_getinfo( _curl,
00824 CURLINFO_EFFECTIVE_URL,
00825 &ptr);
00826 if ( ret == CURLE_OK && ptr != NULL)
00827 {
00828 try
00829 {
00830 Url eurl( ptr);
00831 std::string path( eurl.getPathName());
00832 if( !path.empty() && path != "/" && *path.rbegin() == '/')
00833 {
00834 DBG << "Effective url ("
00835 << eurl
00836 << ") seems to provide the index of a directory"
00837 << endl;
00838 not_a_file = true;
00839 }
00840 }
00841 catch( ... )
00842 {}
00843 }
00844
00845 if( not_a_file)
00846 {
00847 ::fclose( file );
00848 filesystem::unlink( destNew );
00849 ZYPP_THROW(MediaNotAFileException(_url, filename));
00850 }
00851 }
00852 #endif // DETECT_DIR_INDEX
00853
00854 mode_t mask;
00855
00856
00857 mask = ::umask(0022); ::umask(mask);
00858 if ( ::fchmod( ::fileno(file), 0644 & ~mask))
00859 {
00860 ERR << "Failed to chmod file " << destNew << endl;
00861 }
00862 ::fclose( file );
00863
00864 if ( rename( destNew, dest ) != 0 ) {
00865 ERR << "Rename failed" << endl;
00866 ZYPP_THROW(MediaWriteException(dest));
00867 }
00868 }
00869
00870
00872
00873
00874
00875
00876
00877
00878
00879 void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const
00880 {
00881 filesystem::DirContent content;
00882 getDirInfo( content, dirname, false );
00883
00884 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
00885 Pathname filename = dirname + it->name;
00886 int res = 0;
00887
00888 switch ( it->type ) {
00889 case filesystem::FT_NOT_AVAIL:
00890 case filesystem::FT_FILE:
00891 getFile( filename );
00892 break;
00893 case filesystem::FT_DIR:
00894 if ( recurse_r ) {
00895 getDir( filename, recurse_r );
00896 } else {
00897 res = assert_dir( localPath( filename ) );
00898 if ( res ) {
00899 WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl;
00900 }
00901 }
00902 break;
00903 default:
00904
00905 break;
00906 }
00907 }
00908 }
00909
00911
00912
00913
00914
00915
00916
00917
00918 void MediaCurl::getDirInfo( std::list<std::string> & retlist,
00919 const Pathname & dirname, bool dots ) const
00920 {
00921 getDirectoryYast( retlist, dirname, dots );
00922 }
00923
00925
00926
00927
00928
00929
00930
00931
00932 void MediaCurl::getDirInfo( filesystem::DirContent & retlist,
00933 const Pathname & dirname, bool dots ) const
00934 {
00935 getDirectoryYast( retlist, dirname, dots );
00936 }
00937
00939
00940
00941
00942
00943
00944
00945
00946 int MediaCurl::progressCallback( void *clientp, double dltotal, double dlnow,
00947 double ultotal, double ulnow )
00948 {
00949 callback::SendReport<DownloadProgressReport> *report
00950 = reinterpret_cast<callback::SendReport<DownloadProgressReport>*>( clientp );
00951 if (report)
00952 {
00953
00954 if (! (*report)->progress(int( dlnow * 100 / dltotal ), Url() ))
00955 return 1;
00956 }
00957 return 0;
00958 }
00959
00960
00961 }
00962 }