~ubuntu-branches/ubuntu/trusty/openscenegraph/trusty

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgPlugins/curl/ReaderWriterCURL.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-07-29 04:34:38 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080729043438-no1h9h0dpsrlzp1y
* Non-maintainer upload.
* No longer try to detect (using /proc/cpuinfo when available) how many
  CPUs are available, fixing the FTBFS (due to -j0) on various platforms
  (Closes: #477353). The right way to do it is to support parallel=n in
  DEB_BUILD_OPTIONS (see Debian Policy §4.9.1), and adequate support has
  been implemented.
* Add patch to fix FTBFS due to the build system now refusing to handle
  whitespaces (Policy CMP0004 say the logs), thanks to Andreas Putzo who
  provided it (Closes: #482239):
   - debian/patches/fix-cmp0004-build-failure.dpatch
* Remove myself from Uploaders, as requested a while ago, done by Luk in
  his 2.2.0-2.1 NMU, which was never acknowledged.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*-c++-*- VirtualPlanetBuilder - Copyright (C) 1998-2007 Robert Osfield 
 
2
 *
 
3
 * This application is open source and may be redistributed and/or modified   
 
4
 * freely and without restriction, both in commericial and non commericial applications,
 
5
 * as long as this copyright notice is maintained.
 
6
 * 
 
7
 * This application is distributed in the hope that it will be useful,
 
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
10
*/
 
11
 
 
12
 
 
13
#include <osgDB/FileUtils>
 
14
#include <osgDB/ReadFile>
 
15
#include <osgDB/WriteFile>
 
16
#include <osgDB/Registry>
 
17
#include <osgDB/FileNameUtils>
 
18
 
 
19
#include <iostream>
 
20
#include <sstream>
 
21
 
 
22
#include <curl/curl.h>
 
23
#include <curl/types.h>
 
24
 
 
25
 
 
26
class ReaderWriterCURL : public osgDB::ReaderWriter
 
27
{
 
28
    public:
 
29
    
 
30
        static size_t StreamMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
 
31
        {
 
32
            size_t realsize = size * nmemb;
 
33
            std::ostream* buffer = (std::ostream*)data;
 
34
 
 
35
            buffer->write((const char*)ptr, realsize);
 
36
 
 
37
            return realsize;
 
38
        }
 
39
 
 
40
 
 
41
        ReaderWriterCURL()
 
42
        {
 
43
            _curl = curl_easy_init();
 
44
            
 
45
            curl_easy_setopt(_curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");            
 
46
            curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, StreamMemoryCallback);
 
47
        }
 
48
      
 
49
        ~ReaderWriterCURL()
 
50
        {
 
51
            if (_curl) curl_easy_cleanup(_curl);
 
52
            
 
53
            _curl = 0;
 
54
        }
 
55
 
 
56
        virtual const char* className() const { return "HTTP Protocol Model Reader"; }
 
57
                                                                                            
 
58
        virtual bool acceptsExtension(const std::string& extension) const
 
59
        {
 
60
            return osgDB::equalCaseInsensitive(extension,"curl");
 
61
        }
 
62
 
 
63
        enum ObjectType
 
64
        {
 
65
            OBJECT,
 
66
            ARCHIVE,
 
67
            IMAGE,
 
68
            HEIGHTFIELD,
 
69
            NODE
 
70
        };
 
71
                                                                                            
 
72
        virtual ReadResult openArchive(const std::string& fileName,ArchiveStatus status, unsigned int , const Options* options) const
 
73
        {
 
74
            if (status!=READ) return ReadResult(ReadResult::FILE_NOT_HANDLED);
 
75
            else return readFile(ARCHIVE,fileName,options);
 
76
        }
 
77
 
 
78
        virtual ReadResult readObject(const std::string& fileName, const Options* options) const
 
79
        {
 
80
            return readFile(OBJECT,fileName,options);
 
81
        }
 
82
                                                                                            
 
83
        virtual ReadResult readImage(const std::string& fileName, const Options *options) const
 
84
        {
 
85
            return readFile(IMAGE,fileName,options);
 
86
        }
 
87
 
 
88
        virtual ReadResult readHeightField(const std::string& fileName, const Options *options) const
 
89
        {
 
90
            return readFile(HEIGHTFIELD,fileName,options);
 
91
        }
 
92
 
 
93
        virtual ReadResult readNode(const std::string& fileName, const Options *options) const
 
94
        {
 
95
            return readFile(NODE,fileName,options);
 
96
        }
 
97
 
 
98
        ReadResult readFile(ObjectType objectType, osgDB::ReaderWriter* rw, std::istream& fin, const Options *options) const
 
99
        {
 
100
            switch(objectType)
 
101
            {
 
102
            case(OBJECT): return rw->readObject(fin,options);
 
103
            case(ARCHIVE): return rw->openArchive(fin,options);
 
104
            case(IMAGE): return rw->readImage(fin,options);
 
105
            case(HEIGHTFIELD): return rw->readHeightField(fin,options);
 
106
            case(NODE): return rw->readNode(fin,options);
 
107
            default: break;
 
108
            }
 
109
            return ReadResult::FILE_NOT_HANDLED;
 
110
        }
 
111
 
 
112
        virtual ReadResult readFile(ObjectType objectType, const std::string& fullFileName, const Options *options) const
 
113
        {
 
114
            std::string cacheFilePath, cacheFileName;
 
115
            std::string proxyAddress, optProxy, optProxyPort;
 
116
 
 
117
            if (options)
 
118
            {
 
119
                std::istringstream iss(options->getOptionString());
 
120
                std::string opt;
 
121
                while (iss >> opt) 
 
122
                {
 
123
                    int index = opt.find( "=" );
 
124
                    if( opt.substr( 0, index ) == "OSG_FILE_CACHE" )
 
125
                        cacheFilePath = opt.substr( index+1 ); //Setting Cache Directory by OSG Options
 
126
                    else if( opt.substr( 0, index ) == "OSG_CURL_PROXY" )
 
127
                        optProxy = opt.substr( index+1 );
 
128
                    else if( opt.substr( 0, index ) == "OSG_CURL_PROXYPORT" )
 
129
                        optProxyPort = opt.substr( index+1 );
 
130
                }
 
131
 
 
132
                //Setting Proxy by OSG Options
 
133
                if(!optProxy.empty())
 
134
                    if(!optProxyPort.empty())
 
135
                        proxyAddress = optProxy + ":" + optProxyPort;
 
136
                    else
 
137
                        proxyAddress = optProxy + ":8080"; //Port not found, using default
 
138
            }
 
139
 
 
140
            if (!osgDB::containsServerAddress(fullFileName)) 
 
141
            {
 
142
                if (options && !(options->getDatabasePathList().empty()))
 
143
                {
 
144
                    if (osgDB::containsServerAddress(options->getDatabasePathList().front()))
 
145
                    {
 
146
                        std::string newFileName = options->getDatabasePathList().front() + "/" + fullFileName;
 
147
                        
 
148
                        return readFile(objectType, newFileName,options);
 
149
                    }
 
150
                }
 
151
 
 
152
                return ReadResult::FILE_NOT_HANDLED;
 
153
            }
 
154
 
 
155
            std::string fileName;
 
156
            std::string ext = osgDB::getFileExtension(fullFileName);
 
157
            if (ext=="curl")
 
158
            {
 
159
                fileName = osgDB::getNameLessExtension(fullFileName);
 
160
            }
 
161
            else
 
162
            {
 
163
                fileName = fullFileName;
 
164
            }
 
165
 
 
166
            osgDB::ReaderWriter *reader = 
 
167
                osgDB::Registry::instance()->getReaderWriterForExtension( osgDB::getFileExtension(fileName));
 
168
                
 
169
            if (!reader)
 
170
            {
 
171
                osg::notify(osg::NOTICE)<<"Error: No ReaderWriter for file "<<fileName<<std::endl;
 
172
                return ReadResult::FILE_NOT_HANDLED;
 
173
            }
 
174
 
 
175
            //Getting CURL Environment Variables (If found rewrite OSG Options)
 
176
            const char* fileCachePath = getenv("OSG_FILE_CACHE");
 
177
            if (fileCachePath) //Env Cache Directory
 
178
                cacheFilePath = std::string(fileCachePath);
 
179
 
 
180
            if (!cacheFilePath.empty())
 
181
            {
 
182
                cacheFileName = cacheFilePath + "/" + 
 
183
                                osgDB::getServerAddress(fileName) + "/" + 
 
184
                                osgDB::getServerFileName(fileName);
 
185
            }
 
186
                                                        
 
187
            if (!cacheFilePath.empty() && osgDB::fileExists(cacheFileName))
 
188
            {
 
189
                osg::notify(osg::INFO) << "Reading cache file " << cacheFileName << std::endl;
 
190
                ReadResult result = osgDB::Registry::instance()->readObject(cacheFileName,options);
 
191
                return result;                
 
192
            }
 
193
 
 
194
            const char* proxyEnvAddress = getenv("OSG_CURL_PROXY");
 
195
            if (proxyEnvAddress) //Env Proxy Settings
 
196
            {
 
197
                const char* proxyEnvPort = getenv("OSG_CURL_PROXYPORT"); //Searching Proxy Port on Env
 
198
 
 
199
                if(proxyEnvPort)
 
200
                    proxyAddress = std::string(proxyEnvAddress) + ":" + std::string(proxyEnvPort);
 
201
                else
 
202
                    proxyAddress = std::string(proxyEnvAddress) + ":8080"; //Default
 
203
            }
 
204
 
 
205
            if(!proxyAddress.empty())
 
206
            {
 
207
                osg::notify(osg::NOTICE)<<"Setting proxy: "<<proxyAddress<<std::endl;
 
208
                curl_easy_setopt(_curl, CURLOPT_PROXY, proxyAddress.c_str()); //Sets proxy address and port on libcurl
 
209
            }
 
210
 
 
211
            std::stringstream buffer;
 
212
 
 
213
            curl_easy_setopt(_curl, CURLOPT_URL, fileName.c_str());
 
214
            curl_easy_setopt(_curl, CURLOPT_WRITEDATA, (void *)&buffer);
 
215
 
 
216
            CURLcode res = curl_easy_perform(_curl);
 
217
            
 
218
 
 
219
            curl_easy_setopt(_curl, CURLOPT_WRITEDATA, (void *)0);
 
220
        
 
221
            if (res==0)
 
222
            {
 
223
                long code;
 
224
                if(!proxyAddress.empty())
 
225
                {
 
226
                    curl_easy_getinfo(_curl, CURLINFO_HTTP_CONNECTCODE, &code);
 
227
                }
 
228
                else
 
229
                {
 
230
                    curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &code);                    
 
231
                }
 
232
                
 
233
                if (code>=400)
 
234
                {
 
235
                    osg::notify(osg::NOTICE)<<"Error: libcurl read error, file="<<fileName<<", error code = "<<code<<std::endl;
 
236
                    return ReadResult::FILE_NOT_FOUND;
 
237
                }
 
238
 
 
239
                osg::ref_ptr<Options> local_opt = const_cast<Options*>(options);
 
240
                if (!local_opt) local_opt = new Options;
 
241
 
 
242
                local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
 
243
 
 
244
                ReadResult readResult = readFile(objectType, reader, buffer, local_opt.get() );
 
245
 
 
246
                local_opt->getDatabasePathList().pop_front();
 
247
 
 
248
                if (!cacheFilePath.empty() && readResult.validObject())
 
249
                {
 
250
                    osg::notify(osg::INFO)<<"Writing cache file "<<cacheFileName<<std::endl;
 
251
                    
 
252
                    std::string filePath = osgDB::getFilePath(cacheFileName);
 
253
                    if (osgDB::fileExists(filePath) || osgDB::makeDirectory(filePath))
 
254
                    {
 
255
                        switch(objectType)
 
256
                        {
 
257
                        case(OBJECT): osgDB::writeObjectFile( *(readResult.getObject()), cacheFileName ); break;
 
258
                        case(IMAGE): osgDB::writeImageFile( *(readResult.getImage()), cacheFileName ); break;
 
259
                        case(HEIGHTFIELD): osgDB::writeHeightFieldFile( *(readResult.getHeightField()), cacheFileName ); break;
 
260
                        case(NODE): osgDB::writeNodeFile( *(readResult.getNode()), cacheFileName ); break;
 
261
                        default: break;
 
262
                        }
 
263
                    }
 
264
                    else
 
265
                    {
 
266
                        osg::notify(osg::NOTICE)<<"Error: Failed to created directory "<<filePath<<std::endl;
 
267
                    }
 
268
 
 
269
                }
 
270
 
 
271
                return readResult;
 
272
            }
 
273
            else
 
274
            {
 
275
                osg::notify(osg::NOTICE)<<"Error: libcurl read error, file="<<fileName<<" error = "<<curl_easy_strerror(res)<<std::endl;
 
276
                return ReadResult::FILE_NOT_HANDLED;
 
277
            }
 
278
        }
 
279
        
 
280
    protected:
 
281
        
 
282
        CURL* _curl;
 
283
        
 
284
};
 
285
 
 
286
 
 
287
 
 
288
// now register with Registry to instantiate the above
 
289
// reader/writer.
 
290
REGISTER_OSGPLUGIN(rgb, ReaderWriterCURL)