big MediaCurl refactoring, to share the settings initialization with
authorDuncan Mac-Vicar P <dmacvicar@suse.de>
Sun, 22 Feb 2009 01:00:25 +0000 (02:00 +0100)
committerDuncan Mac-Vicar P <dmacvicar@suse.de>
Sun, 22 Feb 2009 01:00:25 +0000 (02:00 +0100)
MediaAria2c.

- replace lot of curl_easy_setop with exception checking to a
  macro to reduce duplicated code
- implement download.min_download_speed (default no limit)
  download.max_download_speed (default no limit) for MediaCurl as well

Still thinking if MediaCurl should be still the default for https, because
aria does not support a CA dir (only files)

zypp/media/MediaAria2c.cc
zypp/media/MediaAria2c.h
zypp/media/MediaCurl.cc
zypp/media/MediaCurl.h
zypp/media/TransferSettings.cc
zypp/media/TransferSettings.h

index e9d04e4..8d00e78 100644 (file)
@@ -26,7 +26,6 @@
 #include "zypp/Target.h"
 #include "zypp/ZYppFactory.h"
 
-#include "zypp/media/TransferProgram.h"
 #include "zypp/media/MediaAria2c.h"
 #include "zypp/media/proxyinfo/ProxyInfos.h"
 #include "zypp/media/ProxyInfo.h"
@@ -75,84 +74,6 @@ MediaAria2c::existsAria2cmd()
     return ( aria.close() == 0 );
 }
 
-void fillSettingsFromUrl( const Url &url, TransferSettings &s )
-{
-    std::string param(url.getQueryParam("timeout"));
-    if( !param.empty())
-    {
-      long num = str::strtonum<long>(param);
-      if( num >= 0 && num <= TRANSFER_TIMEOUT_MAX)
-          s.setTimeout(num);
-    }
-
-    if ( ! url.getUsername().empty() )
-    {
-        s.setUsername(url.getUsername());
-        if ( url.getPassword().size() )
-        {
-            s.setPassword(url.getPassword());
-        }
-    }
-
-    string proxy = url.getQueryParam( "proxy" );
-
-    if ( ! proxy.empty() )
-    {
-        string proxyport( url.getQueryParam( "proxyport" ) );
-        if ( ! proxyport.empty() ) {
-            proxy += ":" + proxyport;
-        }
-        s.setProxy(proxy);
-        s.setProxyEnabled(true);
-    }
-}    
-
-void fillSettingsSystemProxy( const Url&url, TransferSettings &s )
-{
-    ProxyInfo proxy_info (ProxyInfo::ImplPtr(new ProxyInfoSysconfig("proxy")));
-
-    if ( proxy_info.enabled())
-    {
-      s.setProxyEnabled(true);
-      std::list<std::string> nope = proxy_info.noProxy();
-      for (ProxyInfo::NoProxyIterator it = proxy_info.noProxyBegin();
-           it != proxy_info.noProxyEnd();
-           it++)
-      {
-        std::string host( str::toLower(url.getHost()));
-        std::string temp( str::toLower(*it));
-
-        // no proxy if it points to a suffix
-        // preceeded by a '.', that maches
-        // the trailing portion of the host.
-        if( temp.size() > 1 && temp.at(0) == '.')
-        {
-          if(host.size() > temp.size() &&
-             host.compare(host.size() - temp.size(), temp.size(), temp) == 0)
-          {
-            DBG << "NO_PROXY: '" << *it  << "' matches host '"
-                                 << host << "'" << endl;
-            s.setProxyEnabled(false);
-            break;
-          }
-        }
-        else
-        // no proxy if we have an exact match
-        if( host == temp)
-        {
-          DBG << "NO_PROXY: '" << *it  << "' matches host '"
-                               << host << "'" << endl;
-          s.setProxyEnabled(false);
-          break;
-        }
-      }
-
-      if ( s.proxyEnabled() )
-          s.setProxy(proxy_info.proxy(url.getScheme()));
-    }
-
-}    
-
 /**
  * comannd line for aria.
  * The argument list gets passed as reference
@@ -250,38 +171,6 @@ void fillAriaCmdLine( const Pathname &ariapath,
     args.push_back(url.asString().c_str());
 }
 
-static const char *const anonymousIdHeader()
-{
-  // we need to add the release and identifier to the
-  // agent string.
-  // The target could be not initialized, and then this information
-  // is not available.
-  Target_Ptr target = zypp::getZYpp()->getTarget();
-
-  static const std::string _value(
-      str::form(
-          "X-Zypp-AnonymousId: %s",
-          target ? target->anonymousUniqueId().c_str() : "" )
-  );
-  return _value.c_str();
-}
-
-static const char *const distributionFlavorHeader()
-{
-  // we need to add the release and identifier to the
-  // agent string.
-  // The target could be not initialized, and then this information
-  // is not available.
-  Target_Ptr target = zypp::getZYpp()->getTarget();
-
-  static const std::string _value(
-      str::trim( str::form(
-          "X-ZYpp-DistributionFlavor: %s",
-          target ? target->distributionFlavor().c_str() : "" ) )
-  );
-  return _value.c_str();
-}
-
 const char *const MediaAria2c::agentString()
 {
   // we need to add the release and identifier to the
@@ -309,28 +198,6 @@ MediaAria2c::MediaAria2c( const Url &      url_r,
 {
   MIL << "MediaAria2c::MediaAria2c(" << url_r << ", " << attach_point_hint_r << ")" << endl;
 
-  /*
-  if( !attachPoint().empty())
-  {
-    PathInfo ainfo(attachPoint());
-    Pathname apath(attachPoint() + "XXXXXX");
-    char    *atemp = ::strdup( apath.asString().c_str());
-    char    *atest = NULL;
-    if( !ainfo.isDir() || !ainfo.userMayRWX() ||
-         atemp == NULL || (atest=::mkdtemp(atemp)) == NULL)
-    {
-      WAR << "attach point " << ainfo.path()
-          << " is not useable for " << url_r.getScheme() << endl;
-      setAttachPoint("", true);
-    }
-    else if( atest != NULL)
-      ::rmdir(atest);
-
-    if( atemp != NULL)
-      ::free(atemp);
-  }
-  */
-
    //At this point, we initialize aria2c path
    _aria2cPath = Pathname( whereisAria2c().asString() );
 
@@ -341,25 +208,7 @@ MediaAria2c::MediaAria2c( const Url &      url_r,
 void MediaAria2c::attachTo (bool next)
 {
   MediaCurl::attachTo(next);
-    
   _settings.setUserAgentString(agentString());
-  _settings.addHeader(anonymousIdHeader());
-  _settings.addHeader(distributionFlavorHeader());
-
-  _settings.setTimeout(TRANSFER_TIMEOUT);
-  _settings.setConnectTimeout(CONNECT_TIMEOUT);
-
-  // fill some settings from url query parameters
-  fillSettingsFromUrl(_url, _settings);
-
-  // if the proxy was not set by url, then look 
-  if ( _settings.proxy().empty() )
-  {
-      // at the system proxy settings
-      fillSettingsSystemProxy(_url, _settings);
-  }
-
-  DBG << "Proxy: " << (_settings.proxy().empty() ? "-none-" : _settings.proxy()) << endl;
 }
 
 bool
@@ -371,7 +220,6 @@ MediaAria2c::checkAttachPoint(const Pathname &apoint) const
 void MediaAria2c::disconnectFrom()
 {
     MediaCurl::disconnectFrom();
-    
 }
 
 void MediaAria2c::releaseFrom( const std::string & ejectDev )
index 33d49f7..544cc8f 100644 (file)
@@ -107,8 +107,6 @@ class MediaAria2c : public MediaCurl {
     /** External process to get aria2c version */
     std::string getAria2cVersion();    
     static std::string _aria2cVersion;
-    
-    TransferSettings _settings;
 };
 
 ///////////////////////////////////////////////////////////////////
index 280c9a7..af797d2 100644 (file)
@@ -183,6 +183,129 @@ namespace zypp {
 //
 ///////////////////////////////////////////////////////////////////
 
+void fillSettingsFromUrl( const Url &url, TransferSettings &s )
+{
+    std::string param(url.getQueryParam("timeout"));
+    if( !param.empty())
+    {
+      long num = str::strtonum<long>(param);
+      if( num >= 0 && num <= TRANSFER_TIMEOUT_MAX)
+          s.setTimeout(num);
+    }
+
+    if ( ! url.getUsername().empty() )
+    {
+        s.setUsername(url.getUsername());
+        if ( url.getPassword().size() )
+            s.setPassword(url.getPassword());
+    }
+    else
+    {
+        // if there is no username, set anonymous auth
+        if ( url.getScheme() == "ftp" && s.username().empty() )
+            s.setAnonymousAuth();
+    }
+        
+    if ( url.getScheme() == "https" )
+    {
+        s.setVerifyPeerEnabled(false);
+        s.setVerifyHostEnabled(false);
+
+        std::string verify( url.getQueryParam("ssl_verify"));
+        if( verify.empty() ||
+            verify == "yes")
+        {
+            s.setVerifyPeerEnabled(true);
+            s.setVerifyHostEnabled(true);
+        }
+        else if( verify == "no")
+        {
+            s.setVerifyPeerEnabled(false);
+            s.setVerifyHostEnabled(false);
+        }
+        else
+        {
+            std::vector<std::string>                 flags;
+            std::vector<std::string>::const_iterator flag;
+            str::split( verify, std::back_inserter(flags), ",");
+            for(flag = flags.begin(); flag != flags.end(); ++flag)
+            {
+                if( *flag == "host")
+                    s.setVerifyHostEnabled(true);
+                else if( *flag == "peer")
+                    s.setVerifyPeerEnabled(true);
+                else
+                    ZYPP_THROW(MediaBadUrlException(url, "Unknown ssl_verify flag"));
+            }
+        }
+    }
+    
+    Pathname ca_path = Pathname(url.getQueryParam("ssl_capath")).asString();
+    if( ! ca_path.empty())
+    {    
+        if( !PathInfo(ca_path).isDir() || !Pathname(ca_path).absolute())
+            ZYPP_THROW(MediaBadUrlException(url, "Invalid ssl_capath path"));
+        else
+            s.setCertificateAuthoritiesPath(ca_path);
+    }
+
+    string proxy = url.getQueryParam( "proxy" );
+    if ( ! proxy.empty() )
+    {
+        string proxyport( url.getQueryParam( "proxyport" ) );
+        if ( ! proxyport.empty() ) {
+            proxy += ":" + proxyport;
+        }
+        s.setProxy(proxy);
+        s.setProxyEnabled(true);
+    }
+}    
+
+void fillSettingsSystemProxy( const Url&url, TransferSettings &s )
+{
+    ProxyInfo proxy_info (ProxyInfo::ImplPtr(new ProxyInfoSysconfig("proxy")));
+
+    if ( proxy_info.enabled())
+    {
+      s.setProxyEnabled(true);
+      std::list<std::string> nope = proxy_info.noProxy();
+      for (ProxyInfo::NoProxyIterator it = proxy_info.noProxyBegin();
+           it != proxy_info.noProxyEnd();
+           it++)
+      {
+        std::string host( str::toLower(url.getHost()));
+        std::string temp( str::toLower(*it));
+
+        // no proxy if it points to a suffix
+        // preceeded by a '.', that maches
+        // the trailing portion of the host.
+        if( temp.size() > 1 && temp.at(0) == '.')
+        {
+          if(host.size() > temp.size() &&
+             host.compare(host.size() - temp.size(), temp.size(), temp) == 0)
+          {
+            DBG << "NO_PROXY: '" << *it  << "' matches host '"
+                                 << host << "'" << endl;
+            s.setProxyEnabled(false);
+            break;
+          }
+        }
+        else
+        // no proxy if we have an exact match
+        if( host == temp)
+        {
+          DBG << "NO_PROXY: '" << *it  << "' matches host '"
+                               << host << "'" << endl;
+          s.setProxyEnabled(false);
+          break;
+        }
+      }
+
+      if ( s.proxyEnabled() )
+          s.setProxy(proxy_info.proxy(url.getScheme()));
+    }
+}    
+
 Pathname MediaCurl::_cookieFile = "/var/lib/YaST2/cookies";
 
 static const char *const anonymousIdHeader()
@@ -217,7 +340,6 @@ static const char *const distributionFlavorHeader()
   return _value.c_str();
 }
 
-
 static const char *const agentString()
 {
   // we need to add the release and identifier to the
@@ -237,7 +359,15 @@ static const char *const agentString()
   return _value.c_str();
 }
 
-
+// we use this define to unbloat code
+#define SET_OPTION(opt,val) { \
+    ret = curl_easy_setopt ( _curl, opt, val ); \
+    if ( ret != 0) { \
+      disconnectFrom(); \
+      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); \
+    } \
+  }
+      
 MediaCurl::MediaCurl( const Url &      url_r,
                       const Pathname & attach_point_hint_r )
     : MediaHandler( url_r, attach_point_hint_r,
@@ -280,13 +410,7 @@ void MediaCurl::setCookieFile( const Pathname &fileName )
 }
 
 ///////////////////////////////////////////////////////////////////
-//
-//
-//        METHOD NAME : MediaCurl::attachTo
-//        METHOD TYPE : PMError
-//
-//        DESCRIPTION : Asserted that not already attached, and attachPoint is a directory.
-//
+
 void MediaCurl::attachTo (bool next)
 {
   if ( next )
@@ -353,148 +477,66 @@ void MediaCurl::attachTo (bool next)
     ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer"));
   }
 
-  ret = curl_easy_setopt( _curl, CURLOPT_FAILONERROR, true );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
+  SET_OPTION(CURLOPT_FAILONERROR,true);
+  SET_OPTION(CURLOPT_NOSIGNAL, 1);
 
-  ret = curl_easy_setopt( _curl, CURLOPT_NOSIGNAL, 1 );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
+  // add custom headers
+  _settings.addHeader(anonymousIdHeader());
+  _settings.addHeader(distributionFlavorHeader());
+  _settings.addHeader("Pragma:");
 
-  /**
-   * Transfer timeout
-   */
-  {
-    _xfer_timeout = TRANSFER_TIMEOUT;
+  _settings.setTimeout(TRANSFER_TIMEOUT);
+  _settings.setConnectTimeout(CONNECT_TIMEOUT);
 
-    std::string param(_url.getQueryParam("timeout"));
-    if( !param.empty())
-    {
-      long num = str::strtonum<long>( param);
-      if( num >= 0 && num <= TRANSFER_TIMEOUT_MAX)
-        _xfer_timeout = num;
-    }
-  }
+  _settings.setUserAgentString(agentString());
 
-  /*
-  ** Connect timeout
-  */
-  ret = curl_easy_setopt( _curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT);
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
+  // fill some settings from url query parameters
+  try
+  {
+      fillSettingsFromUrl(_url, _settings);
   }
-
-  if ( _url.getScheme() == "http" ) {
-    // follow any Location: header that the server sends as part of
-    // an HTTP header (#113275)
-    ret = curl_easy_setopt ( _curl, CURLOPT_FOLLOWLOCATION, true );
-    if ( ret != 0) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
-    ret = curl_easy_setopt ( _curl, CURLOPT_MAXREDIRS, 3L );
-    if ( ret != 0) {
+  catch ( const MediaException &e )
+  {
       disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
+      ZYPP_RETHROW(e);
+  }
+  
+  // if the proxy was not set by url, then look 
+  if ( _settings.proxy().empty() )
+  {
+      // at the system proxy settings
+      fillSettingsSystemProxy(_url, _settings);
+  }
 
-    ret = curl_easy_setopt ( _curl, CURLOPT_USERAGENT, agentString() );
+  DBG << "Proxy: " << (_settings.proxy().empty() ? "-none-" : _settings.proxy()) << endl;
 
+ /**
+  * Connect timeout
+  */
+  SET_OPTION(CURLOPT_CONNECTTIMEOUT, _settings.connectTimeout());
 
-    if ( ret != 0) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
+  if ( _url.getScheme() == "http" )
+  {
+    // follow any Location: header that the server sends as part of
+    // an HTTP header (#113275)
+    SET_OPTION(CURLOPT_FOLLOWLOCATION, true);
+    SET_OPTION(CURLOPT_MAXREDIRS, 3L);
+    SET_OPTION(CURLOPT_USERAGENT, _settings.userAgentString().c_str() );
   }
 
   if ( _url.getScheme() == "https" )
   {
-    bool verify_peer = false;
-    bool verify_host = false;
-
-    std::string verify( _url.getQueryParam("ssl_verify"));
-    if( verify.empty() ||
-        verify == "yes")
-    {
-      verify_peer = true;
-      verify_host = true;
-    }
-    else
-    if( verify == "no")
-    {
-      verify_peer = false;
-      verify_host = false;
-    }
-    else
-    {
-      std::vector<std::string>                 flags;
-      std::vector<std::string>::const_iterator flag;
-      str::split( verify, std::back_inserter(flags), ",");
-      for(flag = flags.begin(); flag != flags.end(); ++flag)
-      {
-        if( *flag == "host")
-        {
-          verify_host = true;
-        }
-        else
-        if( *flag == "peer")
-        {
-          verify_peer = true;
-        }
-        else
-        {
-                disconnectFrom();
-          ZYPP_THROW(MediaBadUrlException(_url, "Unknown ssl_verify flag"));
-        }
-      }
-    }
-
-    _ca_path = Pathname(_url.getQueryParam("ssl_capath")).asString();
-    if( _ca_path.empty())
-    {
-        _ca_path = "/etc/ssl/certs/";
-    }
-    else
-    if( !PathInfo(_ca_path).isDir() || !Pathname(_ca_path).absolute())
-    {
-        disconnectFrom();
-        ZYPP_THROW(MediaBadUrlException(_url, "Invalid ssl_capath path"));
-    }
-
-    if( verify_peer || verify_host)
+    if( _settings.verifyPeerEnabled() || 
+        _settings.verifyHostEnabled() )
     {
-      ret = curl_easy_setopt( _curl, CURLOPT_CAPATH, _ca_path.c_str());
-      if ( ret != 0 ) {
-        disconnectFrom();
-        ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-      }
-    }
-
-    ret = curl_easy_setopt( _curl, CURLOPT_SSL_VERIFYPEER, verify_peer ? 1L : 0L);
-    if ( ret != 0 ) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
-    ret = curl_easy_setopt( _curl, CURLOPT_SSL_VERIFYHOST, verify_host ? 2L : 0L);
-    if ( ret != 0 ) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
-
-    ret = curl_easy_setopt ( _curl, CURLOPT_USERAGENT, agentString() );
-    if ( ret != 0) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
+      SET_OPTION(CURLOPT_CAPATH, _settings.certificateAuthoritiesPath().c_str());      
     }
 
+    SET_OPTION(CURLOPT_SSL_VERIFYPEER, _settings.verifyPeerEnabled() ? 1L : 0L);
+    SET_OPTION(CURLOPT_SSL_VERIFYHOST, _settings.verifyHostEnabled() ? 2L : 0L);
+    SET_OPTION(CURLOPT_USERAGENT, _settings.userAgentString().c_str() );
   }
 
-
   /*---------------------------------------------------------------*
    CURLOPT_USERPWD: [user name]:[password]
 
@@ -502,27 +544,12 @@ void MediaCurl::attachTo (bool next)
    If not provided, anonymous FTP identification
    *---------------------------------------------------------------*/
 
-  if ( _url.getUsername().empty() ) {
-    if ( _url.getScheme() == "ftp" ) {
-      string id = "yast2@";
-      id += VERSION;
-      DBG << "Anonymous FTP identification: '" << id << "'" << endl;
-      _userpwd = "anonymous:" + id;
-    }
-  } else {
-    _userpwd = _url.getUsername();
-    if ( _url.getPassword().size() ) {
-      _userpwd += ":" + _url.getPassword();
-    }
-  }
+  if ( _settings.userPassword().size() )
+  {
+    SET_OPTION(CURLOPT_USERPWD, unEscape(_settings.userPassword()).c_str());
 
-  if ( _userpwd.size() ) {
-    _userpwd = unEscape( _userpwd );
-    ret = curl_easy_setopt( _curl, CURLOPT_USERPWD, _userpwd.c_str() );
-    if ( ret != 0 ) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
+    //FIXME, we leave this here for now, as it does not make sense yet
+    // to refactor it to the fill settings from url function
 
     // HTTP authentication type
     if(_url.getScheme() == "http" || _url.getScheme() == "https")
@@ -539,11 +566,7 @@ void MediaCurl::attachTo (bool next)
           DBG << "Enabling HTTP authentication methods: " << use_auth
               << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl;
 
-          ret = curl_easy_setopt( _curl, CURLOPT_HTTPAUTH, auth);
-          if ( ret != 0 ) {
-            disconnectFrom();
-            ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-          }
+          SET_OPTION(CURLOPT_HTTPAUTH, auth);
         }
       }
       catch (MediaException & ex_r)
@@ -560,177 +583,72 @@ void MediaCurl::attachTo (bool next)
     }
   }
 
-  /*---------------------------------------------------------------*
-   CURLOPT_PROXY: host[:port]
-
-   Url::option(proxy and proxyport) -> CURLOPT_PROXY
-   If not provided, /etc/sysconfig/proxy is evaluated
-   *---------------------------------------------------------------*/
-
-  _proxy = _url.getQueryParam( "proxy" );
-
-  if ( ! _proxy.empty() ) {
-    string proxyport( _url.getQueryParam( "proxyport" ) );
-    if ( ! proxyport.empty() ) {
-      _proxy += ":" + proxyport;
-    }
-  } else {
-
-    ProxyInfo proxy_info (ProxyInfo::ImplPtr(new ProxyInfoSysconfig("proxy")));
-
-    if ( proxy_info.enabled())
+  if ( _settings.proxyEnabled() )
+  {
+    if ( ! _settings.proxy().empty() )
     {
-      bool useproxy = true;
-
-      std::list<std::string> nope = proxy_info.noProxy();
-      for (ProxyInfo::NoProxyIterator it = proxy_info.noProxyBegin();
-           it != proxy_info.noProxyEnd();
-           it++)
+      SET_OPTION(CURLOPT_PROXY, _settings.proxy().c_str());
+      /*---------------------------------------------------------------*
+        CURLOPT_PROXYUSERPWD: [user name]:[password]
+        
+        Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD
+        If not provided, $HOME/.curlrc is evaluated
+        *---------------------------------------------------------------*/
+      
+      string proxyuserpwd = _settings.proxyUserPassword();
+
+      if ( proxyuserpwd.empty() )
       {
-        std::string host( str::toLower(_url.getHost()));
-        std::string temp( str::toLower(*it));
-
-        // no proxy if it points to a suffix
-        // preceeded by a '.', that maches
-        // the trailing portion of the host.
-        if( temp.size() > 1 && temp.at(0) == '.')
-        {
-          if(host.size() > temp.size() &&
-             host.compare(host.size() - temp.size(), temp.size(), temp) == 0)
-          {
-            DBG << "NO_PROXY: '" << *it  << "' matches host '"
-                                 << host << "'" << endl;
-            useproxy = false;
-            break;
-          }
-        }
+        if (curlconf.proxyuserpwd.empty())
+          DBG << "~/.curlrc does not contain the proxy-user option" << endl;
         else
-        // no proxy if we have an exact match
-        if( host == temp)
         {
-          DBG << "NO_PROXY: '" << *it  << "' matches host '"
-                               << host << "'" << endl;
-          useproxy = false;
-          break;
+          proxyuserpwd = curlconf.proxyuserpwd;
+          DBG << "using proxy-user from ~/.curlrc" << endl;
         }
       }
 
-      if ( useproxy ) {
-        _proxy = proxy_info.proxy(_url.getScheme());
-      }
+      proxyuserpwd = unEscape( proxyuserpwd );
+      if ( ! proxyuserpwd.empty() )
+        SET_OPTION(CURLOPT_PROXYUSERPWD, proxyuserpwd.c_str());
     }
   }
-
-
-  DBG << "Proxy: " << (_proxy.empty() ? "-none-" : _proxy) << endl;
-
-  if ( ! _proxy.empty() ) {
-
-    ret = curl_easy_setopt( _curl, CURLOPT_PROXY, _proxy.c_str() );
-    if ( ret != 0 ) {
-      disconnectFrom();
-      ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-    }
-
-    /*---------------------------------------------------------------*
-     CURLOPT_PROXYUSERPWD: [user name]:[password]
-
-     Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD
-     If not provided, $HOME/.curlrc is evaluated
-     *---------------------------------------------------------------*/
-
-    _proxyuserpwd = _url.getQueryParam( "proxyuser" );
-
-    if ( ! _proxyuserpwd.empty() ) {
-      string proxypassword( _url.getQueryParam( "proxypassword" ) );
-      if ( ! proxypassword.empty() ) {
-        _proxyuserpwd += ":" + proxypassword;
-      }
-    } else {
-      if (curlconf.proxyuserpwd.empty())
-        DBG << "~/.curlrc does not contain the proxy-user option" << endl;
-      else
-      {
-        _proxyuserpwd = curlconf.proxyuserpwd;
-        DBG << "using proxy-user from ~/.curlrc" << endl;
-      }
-    }
-
-    _proxyuserpwd = unEscape( _proxyuserpwd );
-    if ( ! _proxyuserpwd.empty() ) {
-        ret = curl_easy_setopt( _curl, CURLOPT_PROXYUSERPWD, _proxyuserpwd.c_str() );
-        if ( ret != 0 ) {
-            disconnectFrom();
-            ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-        }
-    }
+  
+  /** Speed limits */
+  if ( _settings.minDownloadSpeed() != 0 )
+  {
+      SET_OPTION(CURLOPT_LOW_SPEED_LIMIT, _settings.minDownloadSpeed());
+      // default to 10 seconds at low speed
+      SET_OPTION(CURLOPT_LOW_SPEED_TIME, 10);
   }
+  
+  if ( _settings.maxDownloadSpeed() != 0 )
+      SET_OPTION(CURLOPT_MAX_RECV_SPEED_LARGE, _settings.maxDownloadSpeed());
 
   /*---------------------------------------------------------------*
    *---------------------------------------------------------------*/
 
   _currentCookieFile = _cookieFile.asString();
-
-  ret = curl_easy_setopt( _curl, CURLOPT_COOKIEFILE,
-                          _currentCookieFile.c_str() );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
-
-  ret = curl_easy_setopt( _curl, CURLOPT_COOKIEJAR,
-                          _currentCookieFile.c_str() );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
-
-  ret = curl_easy_setopt( _curl, CURLOPT_PROGRESSFUNCTION,
-                          &progressCallback );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
-
-  ret = curl_easy_setopt( _curl, CURLOPT_NOPROGRESS, false );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
+  SET_OPTION(CURLOPT_COOKIEFILE, _currentCookieFile.c_str() );
+  SET_OPTION(CURLOPT_COOKIEJAR, _currentCookieFile.c_str() );
+  SET_OPTION(CURLOPT_PROGRESSFUNCTION, &progressCallback );
+  SET_OPTION(CURLOPT_NOPROGRESS, false );
 
   // bnc #306272
-  ret = curl_easy_setopt( _curl, CURLOPT_PROXY_TRANSFER_MODE, 1 );
-  if ( ret != 0 ) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
-
-  _customHeaders = curl_slist_append(_customHeaders, "Pragma:");
-
-  if ( !_customHeaders ) {
-      ZYPP_THROW(MediaCurlInitException(_url));
-  }
-
-  // now add the anonymous id header
-  _customHeaders = curl_slist_append(_customHeaders, anonymousIdHeader());
+  SET_OPTION(CURLOPT_PROXY_TRANSFER_MODE, 1 );
 
-  if ( !_customHeaders ) {
-      ZYPP_THROW(MediaCurlInitException(_url));
-  }
-
-  // now add the product flavor header
-  _customHeaders = curl_slist_append(_customHeaders, distributionFlavorHeader());
-
-  if ( !_customHeaders ) {
-      ZYPP_THROW(MediaCurlInitException(_url));
+  // append settings custom headers to curl
+  for ( TransferSettings::Headers::const_iterator it = _settings.headersBegin();
+        it != _settings.headersEnd();
+        ++it )
+  {
+      
+      _customHeaders = curl_slist_append(_customHeaders, it->c_str());
+      if ( !_customHeaders )
+          ZYPP_THROW(MediaCurlInitException(_url));
   }
 
-  ret = curl_easy_setopt ( _curl, CURLOPT_HTTPHEADER, _customHeaders );
-
-  if ( ret != 0) {
-    disconnectFrom();
-    ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
-  }
+  SET_OPTION(CURLOPT_HTTPHEADER, _customHeaders);
 
   // FIXME: need a derived class to propelly compare url's
   MediaSourceRef media( new MediaSource(_url.getScheme(), _url.asString()));
@@ -1163,7 +1081,7 @@ bool MediaCurl::doGetDoesFileExist( const Pathname & filename ) const
 }
 
 
-void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report) const
+void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
 {
     DBG << filename.asString() << endl;
 
@@ -1262,7 +1180,7 @@ void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & targ
     }
 
     // Set callback and perform.
-    ProgressData progressData(_xfer_timeout, url, &report);
+    ProgressData progressData(_settings.timeout(), url, &report);
     report->start(url, dest);
     if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) {
       WAR << "Can't set CURLOPT_PROGRESSDATA: " << _curlError << endl;;
@@ -1734,10 +1652,12 @@ bool MediaCurl::authenticate(const string & availAuthTypes, bool firstTry) const
   // set username and password
   if (credentials)
   {
-    _userpwd = credentials->getUserPwd();
+    // HACK, why is this const?
+    const_cast<MediaCurl*>(this)->_settings.setUsername(credentials->username());
+    const_cast<MediaCurl*>(this)->_settings.setPassword(credentials->password());
 
     // set username and password
-    CURLcode ret = curl_easy_setopt(_curl, CURLOPT_USERPWD, _userpwd.c_str());
+    CURLcode ret = curl_easy_setopt(_curl, CURLOPT_USERPWD, _settings.userPassword().c_str());
     if ( ret != 0 ) ZYPP_THROW(MediaCurlSetOptException(_url, _curlError));
 
     // set available authentication types from the exception
index 248341b..6be4bdb 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef ZYPP_MEDIA_MEDIACURL_H
 #define ZYPP_MEDIA_MEDIACURL_H
 
+#include "zypp/base/Flags.h"
+#include "zypp/media/TransferSettings.h"
 #include "zypp/media/MediaHandler.h"
 #include "zypp/ZYppCallbacks.h"
 
@@ -27,7 +29,19 @@ namespace zypp {
  * @short Implementation class for FTP, HTTP and HTTPS MediaHandler
  * @see MediaHandler
  **/
-class MediaCurl : public MediaHandler {
+class MediaCurl : public MediaHandler
+{
+  public:
+    enum RequestOption
+    {
+        /** Defaults */
+        OPTION_NONE = 0x0,
+        /** retrieve only a range of the file */
+        OPTION_RANGE = 0x1,
+        /** only issue a HEAD (or equivalent) request */
+        OPTION_HEAD = 0x02,
+    };
+    ZYPP_DECLARE_FLAGS(RequestOptions,RequestOption);
 
   protected:
 
@@ -69,7 +83,7 @@ class MediaCurl : public MediaHandler {
      * \throws MediaException
      *
      */
-    virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report) const;
+    virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
 
 
     virtual bool checkAttachPoint(const Pathname &apoint) const;
@@ -109,15 +123,20 @@ class MediaCurl : public MediaHandler {
     long _curlDebug;
     curl_slist *_customHeaders;
 
+    /*
     mutable std::string _userpwd;
     std::string _proxy;
     std::string _proxyuserpwd;
+    */
     std::string _currentCookieFile;
-    std::string _ca_path;
-    long        _xfer_timeout;
+    //std::string _ca_path;
+    //long        _xfer_timeout;
 
     static Pathname _cookieFile;
+protected:
+    TransferSettings _settings;
 };
+ZYPP_DECLARE_OPERATORS_FOR_FLAGS(MediaCurl::RequestOptions);
 
 ///////////////////////////////////////////////////////////////////
 
index b206d1b..e822f27 100644 (file)
@@ -32,6 +32,9 @@ public:
         , _minDownloadSpeed(ZConfig::instance().download_min_download_speed())
         , _maxDownloadSpeed(ZConfig::instance().download_max_download_speed())
         , _maxSilentTries(ZConfig::instance().download_max_silent_tries())
+        , _verify_host(false)
+        , _verify_peer(false)
+        , _ca_path("/etc/ssl/certs")
     {}
 
     virtual ~Impl()
@@ -68,6 +71,10 @@ public:
     long _minDownloadSpeed;
     long _maxDownloadSpeed;
     long _maxSilentTries;
+
+    bool _verify_host;
+    bool _verify_peer;
+    Pathname _ca_path;
 };
     
 TransferSettings::TransferSettings()
@@ -116,11 +123,27 @@ void TransferSettings::setPassword( const std::string &password )
     _impl->_password = password;
 }
 
+void TransferSettings::setAnonymousAuth()
+{
+    setUsername("anonymous");
+    string id = "yast@";
+    setPassword(id + VERSION);
+}
+
 std::string TransferSettings::password() const
 {
     return _impl->_password;
 }
 
+std::string TransferSettings::userPassword() const
+{
+    string userpwd = username();
+    if ( password().size() ) {
+        userpwd += ":" + password();
+    }
+    return userpwd;
+}
+
 void TransferSettings::setProxyEnabled( bool enabled )
 {
     _impl->_useproxy = enabled;
@@ -161,6 +184,15 @@ std::string TransferSettings::proxyPassword() const
     return _impl->_proxy_password;
 }
 
+std::string TransferSettings::proxyUserPassword() const
+{
+    string userpwd = proxyUsername();
+    if ( proxyPassword().size() ) {
+        userpwd += ":" + proxyPassword();
+    }
+    return userpwd;
+}
+
 void TransferSettings::setTimeout( long t )
 {
     _impl->_timeout = t;
@@ -221,6 +253,38 @@ void TransferSettings::setMaxSilentTries(long v)
     _impl->_maxSilentTries = v;
 }
 
+bool TransferSettings::verifyHostEnabled() const
+{
+    return _impl->_verify_host;
+}
+
+void TransferSettings::setVerifyHostEnabled( bool enabled )
+{
+    _impl->_verify_host = enabled;
+}
+
+bool TransferSettings::verifyPeerEnabled() const
+{
+    return _impl->_verify_peer;
+}
+
+
+void TransferSettings::setVerifyPeerEnabled( bool enabled )
+{
+    _impl->_verify_peer = enabled;
+}
+
+Pathname TransferSettings::certificateAuthoritiesPath() const
+{
+    return _impl->_ca_path;
+}
+
+void TransferSettings::setCertificateAuthoritiesPath( const zypp::Pathname &path )
+{
+    _impl->_ca_path = path;
+}
+
+
 } // ns media
 } // ns zypp
 
index 1491bb7..567fff9 100644 (file)
@@ -79,6 +79,17 @@ public:
   std::string password() const;
 
   /**
+   * returns the user and password as 
+   * a user:pass string
+   */
+  std::string userPassword() const;
+
+  /**
+   * sets anonymous authentication (ie: for ftp)
+   */
+  void setAnonymousAuth();
+
+  /**
    * whether the proxy is used or not
    */
   void setProxyEnabled( bool enabled );
@@ -119,6 +130,12 @@ public:
   std::string proxyPassword() const;
 
   /**
+   * returns the proxy user and password as 
+   * a user:pass string
+   */
+  std::string proxyUserPassword() const;
+
+  /**
    * set the connect timeout
    */
   void setConnectTimeout( long t );
@@ -180,6 +197,37 @@ public:
    */
   void setMaxSilentTries(long v);
 
+  /**
+   * Whether to verify host for ssl
+   */
+  bool verifyHostEnabled() const;
+
+  /**
+   * Sets whether to verify host for ssl
+   */
+  void setVerifyHostEnabled( bool enabled );
+
+  /**
+   * Whether to verify peer for ssl
+   */
+  bool verifyPeerEnabled() const;
+
+  /**
+   * Sets whether to verify host for ssl
+   */
+  void setVerifyPeerEnabled( bool enabled );
+
+  /**
+   * SSL certificate authorities path
+   * ( default: /etc/ssl/certs )
+   */
+  Pathname certificateAuthoritiesPath() const;
+
+  /**
+   * Sets the SSL certificate authorities path
+   */
+  void setCertificateAuthoritiesPath( const zypp::Pathname &path );
+
 protected:
   class Impl;
   RWCOW_pointer<Impl> _impl;