⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readerwritercurl.cpp

📁 最新osg包
💻 CPP
字号:
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield  * * This library is open source and may be redistributed and/or modified under   * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or  * (at your option) any later version.  The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * OpenSceneGraph Public License for more details.*/#include <osgDB/FileUtils>#include <osgDB/ReadFile>#include <osgDB/WriteFile>#include <osgDB/Registry>#include <iostream>#include <sstream>#include <fstream>#include <curl/curl.h>#include <curl/types.h>#include "ReaderWriterCURL.h"using namespace osg_curl;////  StreamObject//    EasyCurl::StreamObject::StreamObject(std::ostream* stream1, const std::string& cacheFileName):    _stream1(stream1),    _cacheFileName(cacheFileName){    _foutOpened = false;}void EasyCurl::StreamObject::write(const char* ptr, size_t realsize){    if (_stream1) _stream1->write(ptr, realsize);    if (!_cacheFileName.empty())    {        if (!_foutOpened)        {            osg::notify(osg::INFO)<<"Writing to cache: "<<_cacheFileName<<std::endl;            _fout.open(_cacheFileName.c_str(), std::ios::out | std::ios::binary);            _foutOpened = true;        }        if (_fout)        {            _fout.write(ptr, realsize);        }    }}    size_t EasyCurl::StreamMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data){    size_t realsize = size * nmemb;    StreamObject* sp = (StreamObject*)data;    sp->write((const char*)ptr, realsize);    return realsize;}///////////////////////////////////////////////////////////////////////////////////////////////////////  EasyCurl//EasyCurl::EasyCurl(){    osg::notify(osg::INFO)<<"EasyCurl::EasyCurl()"<<std::endl;        _previousHttpAuthentication = 0;    _curl = curl_easy_init();    curl_easy_setopt(_curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");                curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, StreamMemoryCallback);}EasyCurl::~EasyCurl(){    osg::notify(osg::INFO)<<"EasyCurl::~EasyCurl()"<<std::endl;    if (_curl) curl_easy_cleanup(_curl);    _curl = 0;}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::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);    CURLcode res = curl_easy_perform(_curl);    curl_easy_setopt(_curl, CURLOPT_WRITEDATA, (void *)0);    if (res==0)    {        long code;        if(!proxyAddress.empty())        {            curl_easy_getinfo(_curl, CURLINFO_HTTP_CONNECTCODE, &code);        }        else        {            curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &code);                            }        //If the code is greater than 400, there was an error        if (code >= 400)        {            osgDB::ReaderWriter::ReadResult::ReadStatus status;            //Distinguish between a client error and a server error            if (code < 500)            {                //A 400 level error indicates a client error                status = osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;            }            else            {                //A 500 level error indicates a server error                status = osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;            }            osgDB::ReaderWriter::ReadResult rr(status);            //Add the error code to the ReadResult            std::stringstream message;            message << "error code = " << code;            rr.message() = message.str();            return rr;        }        return osgDB::ReaderWriter::ReadResult::FILE_LOADED;    }    else    {        osg::notify(osg::NOTICE)<<"Error: libcurl read error, file="<<fileName<<" error = "<<curl_easy_strerror(res)<<std::endl;        return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;    }}///////////////////////////////////////////////////////////////////////////////////////////////////////  ReaderWriterCURL//ReaderWriterCURL::ReaderWriterCURL(){    supportsProtocol("http","Read from http port using libcurl.");    supportsExtension("curl","Psuedo file extension, used to select curl plugin.");    supportsExtension("*","Passes all read files to other plugins to handle actual model loading.");    supportsOption("OSG_CURL_PROXY","Specify the http proxy.");    supportsOption("OSG_CURL_PROXYPORT","Specify the http proxy oirt.");}ReaderWriterCURL::~ReaderWriterCURL(){    //osg::notify(osg::NOTICE)<<"ReaderWriterCURL::~ReaderWriterCURL()"<<std::endl;}osgDB::ReaderWriter::ReadResult ReaderWriterCURL::readFile(ObjectType objectType, osgDB::ReaderWriter* rw, std::istream& fin, const osgDB::ReaderWriter::Options *options) const{    switch(objectType)    {    case(OBJECT): return rw->readObject(fin,options);    case(ARCHIVE): return rw->openArchive(fin,options);    case(IMAGE): return rw->readImage(fin,options);    case(HEIGHTFIELD): return rw->readHeightField(fin,options);    case(NODE): return rw->readNode(fin,options);    default: break;    }    return ReadResult::FILE_NOT_HANDLED;}osgDB::ReaderWriter::ReadResult ReaderWriterCURL::readFile(ObjectType objectType, const std::string& fullFileName, const osgDB::ReaderWriter::Options *options) const{    if (!osgDB::containsServerAddress(fullFileName))     {        if (options && !options->getDatabasePathList().empty())        {                    if (osgDB::containsServerAddress(options->getDatabasePathList().front()))            {                std::string newFileName = options->getDatabasePathList().front() + "/" + fullFileName;                return readFile(objectType, newFileName,options);            }        }        return ReadResult::FILE_NOT_HANDLED;    }    osg::notify(osg::INFO)<<"ReaderWriterCURL::readFile("<<fullFileName<<")"<<std::endl;    std::string proxyAddress, optProxy, optProxyPort;    if (options)    {        std::istringstream iss(options->getOptionString());        std::string opt;        while (iss >> opt)         {            int index = opt.find( "=" );            if( opt.substr( 0, index ) == "OSG_CURL_PROXY" )                optProxy = opt.substr( index+1 );            else if( opt.substr( 0, index ) == "OSG_CURL_PROXYPORT" )                optProxyPort = opt.substr( index+1 );        }        //Setting Proxy by OSG Options        if(!optProxy.empty())            if(!optProxyPort.empty())                proxyAddress = optProxy + ":" + optProxyPort;            else                proxyAddress = optProxy + ":8080"; //Port not found, using default    }    std::string fileName;    std::string ext = osgDB::getFileExtension(fullFileName);    if (ext=="curl")    {        fileName = osgDB::getNameLessExtension(fullFileName);        ext = osgDB::getFileExtension(fileName);    }    else    {        fileName = fullFileName;    }        bool uncompress = false;        if (ext=="gz" || ext=="osgz" || ext=="ivez")    {        osg::notify(osg::NOTICE)<<"Compressed file type "<<ext<<std::endl;                #ifndef USE_ZLIB            // don't have zlib so can't compile compressed formats            return ReadResult::FILE_NOT_HANDLED;        #endif                uncompress = true;                if (ext=="gz")        {            ext = osgDB::getFileExtension(fileName);            fileName = osgDB::getNameLessExtension(fileName);        }         else if (ext=="osgz")        {            ext = "osg";        }        else if (ext=="ivez")        {            ext = "ive";        }        osg::notify(osg::NOTICE)<<"  assuming file type "<<ext<<std::endl;    }    osgDB::ReaderWriter *reader =         osgDB::Registry::instance()->getReaderWriterForExtension( ext );    if (!reader)    {        osg::notify(osg::NOTICE)<<"Error: No ReaderWriter for file "<<fileName<<std::endl;        return ReadResult::FILE_NOT_HANDLED;    }    const char* proxyEnvAddress = getenv("OSG_CURL_PROXY");    if (proxyEnvAddress) //Env Proxy Settings    {        const char* proxyEnvPort = getenv("OSG_CURL_PROXYPORT"); //Searching Proxy Port on Env        if(proxyEnvPort)            proxyAddress = std::string(proxyEnvAddress) + ":" + std::string(proxyEnvPort);        else            proxyAddress = std::string(proxyEnvAddress) + ":8080"; //Default    }        std::stringstream buffer;    EasyCurl::StreamObject sp(&buffer, std::string());    ReadResult curlResult = getEasyCurl().read(proxyAddress, fileName, sp, options);    if (curlResult.status()==ReadResult::FILE_LOADED)    {        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));        if (uncompress)        {            std::string uncompressed;            if (!read(buffer, uncompressed))            {                return ReadResult::FILE_NOT_HANDLED;            }                        buffer.str(uncompressed);        }                ReadResult readResult = readFile(objectType, reader, buffer, local_opt.get() );        local_opt->getDatabasePathList().pop_front();        return readResult;    }    else    {        return curlResult;    }}#ifdef USE_ZLIB#include <zlib.h>bool ReaderWriterCURL::read(std::istream& fin, std::string& destination) const{    #define CHUNK 16384    int ret;    unsigned have;    z_stream strm;    unsigned char in[CHUNK];    unsigned char out[CHUNK];    /* allocate inflate state */    strm.zalloc = Z_NULL;    strm.zfree = Z_NULL;    strm.opaque = Z_NULL;    strm.avail_in = 0;    strm.next_in = Z_NULL;    ret = inflateInit2(&strm,                       15 + 32 // autodected zlib or gzip header                       );    if (ret != Z_OK)        return ret;    /* decompress until deflate stream ends or end of file */    do {        strm.avail_in = fin.readsome((char*)in, CHUNK);        if (fin.fail())        {            (void)inflateEnd(&strm);            return false;        }        if (strm.avail_in == 0)            break;        strm.next_in = in;        /* run inflate() on input until output buffer not full */        do {            strm.avail_out = CHUNK;            strm.next_out = out;            ret = inflate(&strm, Z_NO_FLUSH);            switch (ret) {            case Z_NEED_DICT:            case Z_DATA_ERROR:            case Z_MEM_ERROR:                (void)inflateEnd(&strm);                return false;            }            have = CHUNK - strm.avail_out;            destination.append((char*)out, have);                    } while (strm.avail_out == 0);        /* done when inflate() says it's done */    } while (ret != Z_STREAM_END);    /* clean up and return */    (void)inflateEnd(&strm);    return ret == Z_STREAM_END ? true : false;}#elsebool ReaderWriterCURL::read(std::istream& fin, std::string& destination) const{    return false;}#endif// now register with Registry to instantiate the above// reader/writer.REGISTER_OSGPLUGIN(curl, ReaderWriterCURL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -