Added osgDB::AuthenticationMap/Details to osgDB and curl plugin to add the ability
to authenticate http transfers
This commit is contained in:
@@ -32,6 +32,54 @@ class Archive;
|
||||
/** list of directories to search through which searching for files. */
|
||||
typedef std::deque<std::string> 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<std::string, osg::ref_ptr<AuthenticationDetails> > 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> _authenticationMap;
|
||||
|
||||
typedef std::map<std::string,void*> PluginDataMap;
|
||||
mutable PluginDataMap _pluginData;
|
||||
@@ -247,6 +302,7 @@ class OSGDB_EXPORT ReaderWriter : public osg::Object
|
||||
ReadStatus _status;
|
||||
std::string _message;
|
||||
osg::ref_ptr<osg::Object> _object;
|
||||
|
||||
};
|
||||
|
||||
class WriteResult
|
||||
|
||||
@@ -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<osg::KdTreeBuilder> _kdTreeBuilder;
|
||||
|
||||
osg::ref_ptr<AuthenticationMap> _authenticationMap;
|
||||
|
||||
bool _createNodeFromImage;
|
||||
|
||||
osg::Object* readObject(DotOsgWrapperMap& dowMap,Input& fr);
|
||||
|
||||
@@ -15,8 +15,43 @@
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/Archive>
|
||||
|
||||
#include <map>
|
||||
|
||||
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<osg::Image*>(_object.get()); }
|
||||
osg::HeightField* ReaderWriter::ReadResult::getHeightField() { return dynamic_cast<osg::HeightField*>(_object.get()); }
|
||||
|
||||
@@ -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()"<<std::endl;
|
||||
|
||||
_previousHttpAuthentication = 0;
|
||||
|
||||
_curl = curl_easy_init();
|
||||
|
||||
@@ -92,14 +94,55 @@ EasyCurl::~EasyCurl()
|
||||
}
|
||||
|
||||
|
||||
osgDB::ReaderWriter::ReadResult EasyCurl::read(const std::string& proxyAddress, const std::string& fileName, StreamObject& sp)
|
||||
osgDB::ReaderWriter::ReadResult EasyCurl::read(const std::string& proxyAddress, const std::string& fileName, StreamObject& sp, const osgDB::ReaderWriter::Options *options)
|
||||
{
|
||||
const osgDB::AuthenticationMap* authenticationMap = (options && options->getAuthenticationMap()) ?
|
||||
options->getAuthenticationMap() :
|
||||
osgDB::Registry::instance()->getAuthenticationMap();
|
||||
|
||||
if(!proxyAddress.empty())
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Setting proxy: "<<proxyAddress<<std::endl;
|
||||
osg::notify(osg::INFO)<<"Setting proxy: "<<proxyAddress<<std::endl;
|
||||
curl_easy_setopt(_curl, CURLOPT_PROXY, proxyAddress.c_str()); //Sets proxy address and port on libcurl
|
||||
}
|
||||
|
||||
const osgDB::AuthenticationDetails* details = authenticationMap ?
|
||||
authenticationMap->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<Options> local_opt = const_cast<Options*>(options);
|
||||
if (!local_opt) local_opt = new Options;
|
||||
osg::ref_ptr<Options> local_opt = options ?
|
||||
static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) :
|
||||
new Options;
|
||||
|
||||
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user