diff --git a/include/osgDB/ReaderWriter b/include/osgDB/ReaderWriter index 27cf30825..f20e10110 100644 --- a/include/osgDB/ReaderWriter +++ b/include/osgDB/ReaderWriter @@ -32,6 +32,54 @@ class Archive; /** list of directories to search through which searching for files. */ typedef std::deque FilePathList; +class AuthenticationDetails : public osg::Referenced +{ +public: + + /** Http authentication techniques, see libcurl docs for details on names and associated functionality.*/ + enum HttpAuthentication + { + BASIC = 1<<0, + DIGEST = 1<<1, + NTLM = 1<<2, + GSSNegotiate = 1<<2, + ANY = ~0, + ANYSAFE = ~BASIC + }; + + AuthenticationDetails(const std::string& u, const std::string& p, HttpAuthentication auth=BASIC): + username(u), + password(p), + httpAuthentication(auth) {} + + std::string username; + std::string password; + HttpAuthentication httpAuthentication; + +protected: + virtual ~AuthenticationDetails() {} +}; + +class OSGDB_EXPORT AuthenticationMap : public osg::Referenced +{ + public: + + AuthenticationMap() {} + + + virtual void addAuthenticationDetails(const std::string& path, AuthenticationDetails* details); + + virtual const AuthenticationDetails* getAuthenticationDetails(const std::string& path) const; + + protected: + + virtual ~AuthenticationMap() {} + + typedef std::map > AuthenticationDetailsMap; + AuthenticationDetailsMap _authenticationMap; + +}; + /** pure virtual base class for reading and writing of non native formats. */ class OSGDB_EXPORT ReaderWriter : public osg::Object { @@ -159,6 +207,12 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object BuildKdTreesHint getBuildKdTreesHint() const { return _buildKdTreesHint; } + /** Set the password map to be used by plugins when access files from secure locations.*/ + void setAuthenticationMap(AuthenticationMap* authenticationMap) { _authenticationMap = authenticationMap; } + + /** Get the password map to be used by plugins when access files from secure locations.*/ + const AuthenticationMap* getAuthenticationMap() const { return _authenticationMap.get(); } + /** Sets a plugindata value PluginData with a string */ void setPluginData(const std::string& s, void* v) const { _pluginData[s] = v; } @@ -180,10 +234,11 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object virtual ~Options() {} - std::string _str; - FilePathList _databasePaths; - CacheHintOptions _objectCacheHint; - BuildKdTreesHint _buildKdTreesHint; + std::string _str; + FilePathList _databasePaths; + CacheHintOptions _objectCacheHint; + BuildKdTreesHint _buildKdTreesHint; + osg::ref_ptr _authenticationMap; typedef std::map PluginDataMap; mutable PluginDataMap _pluginData; @@ -247,6 +302,7 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object ReadStatus _status; std::string _message; osg::ref_ptr _object; + }; class WriteResult diff --git a/include/osgDB/Registry b/include/osgDB/Registry index 9a4dae6b4..2110f46fa 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -334,16 +334,29 @@ class OSGDB_EXPORT Registry : public osg::Referenced } + /** Set whether the KdTrees should be built for geometry in the loader model. */ void setBuildKdTreesHint(ReaderWriter::Options::BuildKdTreesHint hint) { _buildKdTreesHint = hint; } + + /** Get whether the KdTrees should be built for geometry in the loader model. */ ReaderWriter::Options::BuildKdTreesHint getBuildKdTreesHint() const { return _buildKdTreesHint; } + /** Set the KdTreeBuilder visitor that is used to build KdTree on loaded models.*/ void setKdTreeBuilder(osg::KdTreeBuilder* builder) { _kdTreeBuilder = builder; } + + /** Get the KdTreeBuilder visitor that is used to build KdTree on loaded models.*/ osg::KdTreeBuilder* getKdTreeBuilder() { return _kdTreeBuilder.get(); } + /** Set the password map to be used by plugins when access files from secure locations.*/ + void setAuthenticationMap(AuthenticationMap* authenticationMap) { _authenticationMap = authenticationMap; } + + /** Get the password map to be used by plugins when access files from secure locations.*/ + const AuthenticationMap* getAuthenticationMap() const { return _authenticationMap.get(); } + + void setCreateNodeFromImage(bool flag) { _createNodeFromImage = flag; } bool getCreateNodeFromImage() const { return _createNodeFromImage; } - + void setOptions(ReaderWriter::Options* opt) { _options = opt; } ReaderWriter::Options* getOptions() { return _options.get(); } @@ -478,6 +491,8 @@ class OSGDB_EXPORT Registry : public osg::Referenced ReaderWriter::Options::BuildKdTreesHint _buildKdTreesHint; osg::ref_ptr _kdTreeBuilder; + osg::ref_ptr _authenticationMap; + bool _createNodeFromImage; osg::Object* readObject(DotOsgWrapperMap& dowMap,Input& fr); diff --git a/src/osgDB/ReaderWriter.cpp b/src/osgDB/ReaderWriter.cpp index 105e955f8..0df3e1033 100644 --- a/src/osgDB/ReaderWriter.cpp +++ b/src/osgDB/ReaderWriter.cpp @@ -15,8 +15,43 @@ #include #include +#include + using namespace osgDB; +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// PasswordMap +// + +void AuthenticationMap::addAuthenticationDetails(const std::string& path, AuthenticationDetails* details) +{ + _authenticationMap[path] = details; +} + +const AuthenticationDetails* AuthenticationMap::getAuthenticationDetails(const std::string& path) const +{ + // see if the full filename has its own authentication details + AuthenticationDetailsMap::const_iterator itr = _authenticationMap.find(path); + if (itr != _authenticationMap.end()) return itr->second.get(); + + // now look to see if the paths to the file have their own authentication details + std::string basePath = osgDB::getFilePath(path); + while(!basePath.empty()) + { + itr = _authenticationMap.find(basePath); + if (itr != _authenticationMap.end()) return itr->second.get(); + + basePath = osgDB::getFilePath(basePath); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// ReaderWriter +// + osg::Object* ReaderWriter::ReadResult::getObject() { return _object.get(); } osg::Image* ReaderWriter::ReadResult::getImage() { return dynamic_cast(_object.get()); } osg::HeightField* ReaderWriter::ReadResult::getHeightField() { return dynamic_cast(_object.get()); } diff --git a/src/osgPlugins/curl/ReaderWriterCURL.cpp b/src/osgPlugins/curl/ReaderWriterCURL.cpp index 8619607cd..f12215421 100644 --- a/src/osgPlugins/curl/ReaderWriterCURL.cpp +++ b/src/osgPlugins/curl/ReaderWriterCURL.cpp @@ -75,6 +75,8 @@ size_t EasyCurl::StreamMemoryCallback(void *ptr, size_t size, size_t nmemb, void EasyCurl::EasyCurl() { osg::notify(osg::INFO)<<"EasyCurl::EasyCurl()"<getAuthenticationMap()) ? + options->getAuthenticationMap() : + osgDB::Registry::instance()->getAuthenticationMap(); + if(!proxyAddress.empty()) { - osg::notify(osg::NOTICE)<<"Setting proxy: "<getAuthenticationDetails(fileName) : + 0; + + // configure/reset authentication if required. + if (details) + { + const std::string colon(":"); + std::string password(details->username + colon + details->password); + curl_easy_setopt(_curl, CURLOPT_USERPWD, password.c_str()); + _previousPassword = password; + + // use for https. + // curl_easy_setopt(_curl, CURLOPT_KEYPASSWD, password.c_str()); + + if (details->httpAuthentication != _previousHttpAuthentication) + { + curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, details->httpAuthentication); + _previousHttpAuthentication = details->httpAuthentication; + } + } + else + { + if (!_previousPassword.empty()) + { + curl_easy_setopt(_curl, CURLOPT_USERPWD, 0); + _previousPassword.clear(); + } + + // need to reset if previously set. + if (_previousHttpAuthentication!=0) + { + curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, 0); + _previousHttpAuthentication = 0; + } + } + curl_easy_setopt(_curl, CURLOPT_URL, fileName.c_str()); curl_easy_setopt(_curl, CURLOPT_WRITEDATA, (void *)&sp); @@ -248,12 +291,13 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCURL::readFile(ObjectType objectType EasyCurl::StreamObject sp(&buffer, std::string()); - ReadResult curlResult = getEasyCurl().read(proxyAddress, fileName, sp); + ReadResult curlResult = getEasyCurl().read(proxyAddress, fileName, sp, options); if (curlResult.status()==ReadResult::FILE_LOADED) { - osg::ref_ptr local_opt = const_cast(options); - if (!local_opt) local_opt = new Options; + osg::ref_ptr local_opt = options ? + static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : + new Options; local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); diff --git a/src/osgPlugins/curl/ReaderWriterCURL.h b/src/osgPlugins/curl/ReaderWriterCURL.h index 3e920bafb..8335bd8f5 100644 --- a/src/osgPlugins/curl/ReaderWriterCURL.h +++ b/src/osgPlugins/curl/ReaderWriterCURL.h @@ -50,7 +50,7 @@ class EasyCurl : public osg::Referenced EasyCurl(); - osgDB::ReaderWriter::ReadResult read(const std::string& proxyAddress, const std::string& fileName, StreamObject& sp); + osgDB::ReaderWriter::ReadResult read(const std::string& proxyAddress, const std::string& fileName, StreamObject& sp, const osgDB::ReaderWriter::Options *options); protected: @@ -62,6 +62,9 @@ class EasyCurl : public osg::Referenced CURL* _curl; + + std::string _previousPassword; + long _previousHttpAuthentication; };