From 71b2b7ab66f7485c133892f9d67ab077a17cb13c Mon Sep 17 00:00:00 2001 From: Jan Kupec Date: Thu, 24 Jan 2008 17:26:36 +0000 Subject: [PATCH] - read .curlrc more robustly (#330351) --- zypp/CMakeLists.txt | 2 + zypp/media/CurlConfig.cc | 168 +++++++++++++++++++++++++++++++++++++++++++++++ zypp/media/CurlConfig.h | 47 +++++++++++++ zypp/media/MediaCurl.cc | 36 +++------- 4 files changed, 226 insertions(+), 27 deletions(-) create mode 100644 zypp/media/CurlConfig.cc create mode 100644 zypp/media/CurlConfig.h diff --git a/zypp/CMakeLists.txt b/zypp/CMakeLists.txt index aec27a0..586be61 100644 --- a/zypp/CMakeLists.txt +++ b/zypp/CMakeLists.txt @@ -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 index 0000000..344ebd9 --- /dev/null +++ b/zypp/media/CurlConfig.cc @@ -0,0 +1,168 @@ +#include +#include + +#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 index 0000000..87b28ed --- /dev/null +++ b/zypp/media/CurlConfig.h @@ -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_*/ diff --git a/zypp/media/MediaCurl.cc b/zypp/media/MediaCurl.cc index c9a2b10..6035831 100644 --- a/zypp/media/MediaCurl.cc +++ b/zypp/media/MediaCurl.cc @@ -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 #include @@ -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 rc_data = base::sysconfig::read( curlrcFile ); - - map::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; } } -- 2.7.4