- read .curlrc more robustly (#330351)
authorJan Kupec <jkupec@suse.cz>
Thu, 24 Jan 2008 17:26:36 +0000 (17:26 +0000)
committerJan Kupec <jkupec@suse.cz>
Thu, 24 Jan 2008 17:26:36 +0000 (17:26 +0000)
zypp/CMakeLists.txt
zypp/media/CurlConfig.cc [new file with mode: 0644]
zypp/media/CurlConfig.h [new file with mode: 0644]
zypp/media/MediaCurl.cc

index aec27a0..586be61 100644 (file)
@@ -379,6 +379,7 @@ SET( zypp_media_SRCS
   media/MediaISO.cc
   media/MediaManager.cc
   media/MediaUserAuth.cc
+  media/CurlConfig.cc
 )
 
 SET( zypp_media_HEADERS
@@ -398,6 +399,7 @@ SET( zypp_media_HEADERS
   media/MediaUserAuth.h
   media/Mount.h
   media/ProxyInfo.h
+  media/CurlConfig.h
 )
 
 INSTALL(  FILES
diff --git a/zypp/media/CurlConfig.cc b/zypp/media/CurlConfig.cc
new file mode 100644 (file)
index 0000000..344ebd9
--- /dev/null
@@ -0,0 +1,168 @@
+#include <iostream>
+#include <fstream>
+
+#include "zypp/base/Logger.h"
+#include "zypp/base/IOStream.h"
+#include "zypp/Pathname.h"
+#include "zypp/PathInfo.h"
+
+#include "zypp/media/CurlConfig.h"
+
+using namespace std;
+
+namespace zypp
+{
+  namespace media
+  {
+
+
+  ///////////////////////////////////////////////////////////////////
+  //
+  //  METHOD NAME : CurlConfig::parseConfig
+  //  METHOD TYPE : int
+  //
+  int CurlConfig::parseConfig(CurlConfig & config, const std::string & filename)
+  {
+    Pathname curlrcFile;
+
+    if(filename.empty())
+    {
+      // attempts to load .curlrc from the homedir
+      char *home = getenv("HOME");
+      if(home)
+        curlrcFile = string( home ) + string( "/.curlrc" );
+    }
+    else
+      curlrcFile = filename;
+
+    PathInfo h_info(curlrcFile.dirname(), PathInfo::LSTAT);
+    PathInfo c_info(curlrcFile,           PathInfo::LSTAT);
+
+    if( h_info.isDir()  && h_info.owner() == getuid() &&
+        c_info.isFile() && c_info.owner() == getuid())
+    {
+      MIL << "Going to parse " << curlrcFile << endl;
+    }
+    else
+    {
+      WAR << "Not allowed to parse '" << curlrcFile
+          << "': bad file owner" << std::endl;
+      return 1;
+    }
+
+    ifstream inp(curlrcFile.c_str());
+    for(iostr::EachLine in( inp ); in; in.next())
+    {
+      string line = str::trim(*in);
+
+      // skip empty lines and comments
+      if (line.empty())
+        continue;
+      switch (line[0])
+      {
+      case '#':
+      case '/':
+      case '\r':
+      case '\n':
+      case '*':
+      case '\0':
+        continue;
+      }
+
+      // DBG << "line " << in.lineNo() << ": " << line << endl; // can't log passwords
+
+      const char * beg = line.c_str();
+      const char * cur = beg;
+
+// space, '=' and ':' are all valid separators in curlrc
+#define ISSEP(x) (((x)=='=') || ((x) == ':') || isspace(x))
+
+      // skip leading dashes (they are optional)
+      while (*cur && *cur == '-')
+        cur++;
+      beg = cur;
+
+      // skip non-separator characters
+      while (*cur && !ISSEP(*cur))
+        cur++;
+
+      string option(beg, cur - beg);
+
+      // skip separator characters
+      while (*cur && ISSEP(*cur))
+        cur++;
+
+      // rewind to the end of the line
+      beg = cur;
+      while (*cur)
+        cur++;
+
+      string value(beg, cur - beg);
+
+      DBG << "GOT: " << option << endl;
+
+      if (!value.empty())
+      {
+        // quoted parameter
+        if (value[0] == '\"')
+        {
+          // remove the quotes
+          string::size_type pos = value.rfind('\"');
+          value = value.substr(1,
+            pos == value.size() - 1 ? value.size() - 2 : value.size() - 1);
+
+          // replace special characters:
+          while ((pos = value.find('\\')) != string::npos)
+          {
+            switch(value[pos+1])
+            {
+            case 't':
+              value = value.replace(pos, 2, "\t");
+              break;
+            case 'n':
+              value = value.replace(pos, 2, "\n");
+              break;
+            case 'r':
+              value = value.replace(pos, 2, "\r");
+              break;
+            case 'v':
+              value = value.replace(pos, 2, "\v");
+              break;
+            default:;
+              value = value.erase(pos, 1);
+            }
+          }
+        }
+
+        // DBG << "PARAM: " << value << endl; // can't log passwords
+      }
+
+      CurlConfig::setParameter(config, option, value);
+    } // for EachLine in curlrc
+
+    return 0;
+  }
+
+
+  ///////////////////////////////////////////////////////////////////
+  //
+  //  METHOD NAME : CurlConfig::setParameter
+  //  METHOD TYPE : int
+  //
+  int CurlConfig::setParameter(CurlConfig & config,
+                               const std::string & option,
+                               const std::string & value)
+  {
+    if (option == "proxy-user")
+      config.proxyuserpwd = value;
+    // add more curl config data here as they become needed
+    // else if (option == "foo")
+    else
+      DBG << "Ignoring option " << option << endl;
+
+    return 0;
+  }
+
+
+  } // namespace media
+} // namespace zypp
diff --git a/zypp/media/CurlConfig.h b/zypp/media/CurlConfig.h
new file mode 100644 (file)
index 0000000..87b28ed
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef ZYPP_MEDIA_CURLRCONFIG_H_
+#define ZYPP_MEDIA_CURLRCONFIG_H_
+
+//#include "zypp/base/NonCopyable.h"
+#include "zypp/base/String.h"
+
+namespace zypp
+{
+  namespace media
+  {
+
+
+  /**
+   * Structure holding values of curlrc options.
+   */
+  struct CurlConfig
+  {
+  public:
+    /**
+     * Parse a curlrc file and store the result in the \a config structure.
+     * 
+     * \param config   a CurlConfig structure
+     * \param filename path to the curlrc file. If empty, ~/.curlrc is used.
+     * \return         0 on success, 1 if problem occurs.
+     */
+    static int parseConfig(CurlConfig & config, const std::string & filename = "");
+
+    /**
+     * Stores the \a value of the \a option in the \a config structure or
+     * logs an unknown option.
+     * 
+     * \return         0 on success, 1 if problem occurs.
+     */
+    static int setParameter(CurlConfig & config,
+                            const std::string & option,
+                            const std::string & value);
+
+  public:
+    std::string proxyuserpwd;
+    // add more curl config data here as they become needed
+  };
+
+
+  } // namespace media
+} // namespace zypp
+
+#endif /*ZYPP_MEDIA_CURLRCONFIG_H_*/
index c9a2b10..6035831 100644 (file)
@@ -23,6 +23,7 @@
 #include "zypp/media/proxyinfo/ProxyInfos.h"
 #include "zypp/media/ProxyInfo.h"
 #include "zypp/media/MediaUserAuth.h"
+#include "zypp/media/CurlConfig.h"
 #include "zypp/thread/Once.h"
 #include <cstdlib>
 #include <sys/types.h>
@@ -220,6 +221,9 @@ void MediaCurl::attachTo (bool next)
   if ( !_url.isValid() )
     ZYPP_THROW(MediaBadUrlException(_url));
 
+  CurlConfig curlconf;
+  CurlConfig::parseConfig(curlconf); // parse ~/.curlrc
+
   curl_version_info_data *curl_info = NULL;
   curl_info = curl_version_info(CURLVERSION_NOW);
   // curl_info does not need any free (is static)
@@ -560,39 +564,17 @@ void MediaCurl::attachTo (bool next)
     _proxyuserpwd = _url.getQueryParam( "proxyuser" );
 
     if ( ! _proxyuserpwd.empty() ) {
-
       string proxypassword( _url.getQueryParam( "proxypassword" ) );
       if ( ! proxypassword.empty() ) {
         _proxyuserpwd += ":" + proxypassword;
       }
-
     } else {
-      char *home = getenv("HOME");
-      if( home && *home)
+      if (curlconf.proxyuserpwd.empty())
+        DBG << "~/.curlrc does not contain the proxy-user option" << endl;
+      else
       {
-              Pathname curlrcFile = string( home ) + string( "/.curlrc" );
-
-        PathInfo h_info(string(home), PathInfo::LSTAT);
-        PathInfo c_info(curlrcFile,   PathInfo::LSTAT);
-
-        if( h_info.isDir()  && h_info.owner() == getuid() &&
-            c_info.isFile() && c_info.owner() == getuid())
-        {
-          //! \todo FIXME adjust to .curlrc syntax: = and -- are optional!#
-
-          map<string,string> rc_data = base::sysconfig::read( curlrcFile );
-
-          map<string,string>::const_iterator it = rc_data.find("--proxy-user");
-          if (it != rc_data.end())
-            _proxyuserpwd = it->second;
-
-          DBG << "got proxy userpwd (--proxy-user) from ~/culrc" << endl;
-        }
-        else
-        {
-          WAR << "Not allowed to parse '" << curlrcFile
-              << "': bad file owner" << std::endl;
-        }
+        _proxyuserpwd = curlconf.proxyuserpwd;
+        DBG << "using proxy-user from ~/.curlrc" << endl;
       }
     }