ref: refs/heads/SuSE-SLE-10-SP3-Branch
commit 8aae88b1734ac36a4ac9cf315caa0f05615cf65d
Author: Ján Kupec
Date: Mon Apr 6 19:22:15 2009 +0200
Read .curlrc more robustly (bnc #330351, bnc #331038)
---
zypp/media/CurlConfig.cc | 181 ++++++++++++++++++++++++++++++++++++++++++++++
zypp/media/CurlConfig.h | 47 ++++++++++++
zypp/media/Makefile.am | 6 +-
zypp/media/MediaCurl.cc | 62 ++++++----------
4 files changed, 256 insertions(+), 40 deletions(-)
diff --git a/zypp/media/CurlConfig.cc b/zypp/media/CurlConfig.cc
new file mode 100644
index 0000000..e2ff121
--- /dev/null
+++ b/zypp/media/CurlConfig.cc
@@ -0,0 +1,181 @@
+#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('\"');
+ bool cut_last =
+ pos == value.size() - 1 && pos > 1 && value[pos-1] != '\\';
+ value = value.substr(1,
+ cut_last ? value.size() - 2 : value.size() - 1);
+
+ // replace special characters:
+ pos = 0;
+ while ((pos = value.find('\\', pos)) != string::npos)
+ {
+ // just erase the backslash if it is found at the end
+ if (pos == value.size() - 1)
+ {
+ value = value.erase(pos, 1);
+ break;
+ }
+
+ 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;
+ case '\\':
+ value = value.erase(pos++, 1);
+ 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/Makefile.am b/zypp/media/Makefile.am
index be45f5c..1c4603f 100644
--- a/zypp/media/Makefile.am
+++ b/zypp/media/Makefile.am
@@ -27,7 +27,8 @@ mediainclude_HEADERS = \
ProxyInfo.h \
MediaCurl.h \
MediaISO.h \
- MediaManager.h
+ MediaManager.h \
+ CurlConfig.h
noinst_LTLIBRARIES = lib@PACKAGE@_media.la
@@ -48,7 +49,8 @@ lib@PACKAGE@_media_la_SOURCES = \
ProxyInfo.cc \
MediaCurl.cc \
MediaISO.cc \
- MediaManager.cc
+ MediaManager.cc \
+ CurlConfig.cc
lib@PACKAGE@_media_la_LIBADD = proxyinfo/lib@PACKAGE@_media_proxyinfo.la \
diff --git a/zypp/media/MediaCurl.cc b/zypp/media/MediaCurl.cc
index 427c382..50781f6 100644
--- a/zypp/media/MediaCurl.cc
+++ b/zypp/media/MediaCurl.cc
@@ -22,6 +22,7 @@
#include "zypp/media/MediaCurl.h"
#include "zypp/media/proxyinfo/ProxyInfos.h"
#include "zypp/media/ProxyInfo.h"
+#include "zypp/media/CurlConfig.h"
#include "zypp/thread/Once.h"
#include <cstdlib>
#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)
@@ -590,35 +594,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())
- {
- map rc_data = base::sysconfig::read( curlrcFile );
-
- map::const_iterator it = rc_data.find("proxy-user");
- if (it != rc_data.end())
- _proxyuserpwd = it->second;
- }
- else
- {
- WAR << "Not allowed to parse '" << curlrcFile
- << "': bad file owner" << std::endl;
- }
+ _proxyuserpwd = curlconf.proxyuserpwd;
+ DBG << "using proxy-user from ~/.curlrc" << endl;
}
}
@@ -744,7 +730,7 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
if(_url.getHost().empty())
ZYPP_THROW(MediaBadUrlEmptyHostException(_url));
-
+
string path = _url.getPathName();
if ( !path.empty() && path != "/" && *path.rbegin() == '/' &&
filename.absolute() ) {
@@ -776,7 +762,7 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
curlUrl.setPathParams( "" );
curlUrl.setQueryString( "" );
curlUrl.setFragment( "" );
-
+
//
// See also Bug #154197 and ftp url definition in RFC 1738:
// The url "ftp://user@host/foo/bar/file" contains a path,
@@ -791,22 +777,22 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
if ( ret != 0 ) {
ZYPP_THROW(MediaCurlSetOptException(url, _curlError));
}
-
+
// set no data, because we only want to check if the file exists
//ret = curl_easy_setopt( _curl, CURLOPT_NOBODY, 1 );
//if ( ret != 0 ) {
// ZYPP_THROW(MediaCurlSetOptException(url, _curlError));
- //}
-
- // instead of returning no data with NOBODY, we return
+ //}
+
+ // instead of returning no data with NOBODY, we return
// little data, that works with broken servers, and
// works for ftp as well, because retrieving only headers
// ftp will return always OK code ?
ret = curl_easy_setopt( _curl, CURLOPT_RANGE, "0-1" );
if ( ret != 0 ) {
ZYPP_THROW(MediaCurlSetOptException(url, _curlError));
- }
-
+ }
+
FILE *file = ::fopen( "/dev/null", "w" );
if ( !file ) {
::fclose(file);
@@ -844,11 +830,11 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
{
ZYPP_THROW(MediaCurlSetOptException(url, _curlError));
}
-
+
if ( ok != 0 )
{
::fclose( file );
-
+
std::string err;
try
{
@@ -856,7 +842,7 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
switch ( ok )
{
case CURLE_FTP_COULDNT_RETR_FILE:
- case CURLE_FTP_ACCESS_DENIED:
+ case CURLE_FTP_ACCESS_DENIED:
err_file_not_found = true;
break;
case CURLE_HTTP_RETURNED_ERROR:
@@ -924,7 +910,7 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
err = "Unrecognized error";
break;
}
-
+
if( err_file_not_found)
{
// file does not exists
@@ -940,14 +926,14 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
{
ZYPP_RETHROW(excpt_r);
}
- }
-
+ }
+
// exists
return ( ok == CURLE_OK );
//if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, NULL ) != 0 ) {
// WAR << "Can't unset CURLOPT_PROGRESSDATA: " << _curlError << endl;;
//}
-}
+}
void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report) const
{
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org