https://issues.shibboleth.net/jira/browse/CPPXT-52
[shibboleth/cpp-xmltooling.git] / xmltooling / util / CurlURLInputStream.h
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /**
19  * @file xmltooling/util/CurlURLInputStream.h
20  *
21  * Asynchronous use of curl to fetch data from a URL.
22  */
23
24 #if !defined(__xmltooling_curlinstr_h__) && !defined(XMLTOOLING_LITE)
25 #define __xmltooling_curlinstr_h__
26
27 #include <xmltooling/logging.h>
28
29 #include <string>
30 #include <vector>
31 #include <curl/curl.h>
32 #include <xercesc/util/BinInputStream.hpp>
33
34 namespace xmltooling {
35
36     /**
37      * Adapted from Xerces-C as a more advanced input stream implementation
38      * for subsequent use in parsing remote documents.
39      */
40     class XMLTOOL_API CurlURLInputStream : public xercesc::BinInputStream
41     {
42     public :
43         /**
44          * Constructor.
45          *
46          * @param url       the URL of the resource to fetch
47          * @param cacheTag  optional pointer to string used for cache management
48          */
49         CurlURLInputStream(const char* url, std::string* cacheTag=NULL);
50
51         /**
52          * Constructor.
53          *
54          * @param url       the URL of the resource to fetch
55          * @param cacheTag  optional pointer to string used for cache management
56          */
57         CurlURLInputStream(const XMLCh* url, std::string* cacheTag=NULL);
58
59         /**
60          * Constructor taking a DOM element supporting the following content:
61          * 
62          * <dl>
63          *  <dt>uri | url</dt>
64          *  <dd>identifies the remote resource</dd>
65          *  <dt>verifyHost</dt>
66          *  <dd>true iff name of host should be matched against TLS/SSL certificate</dd>
67          *  <dt>TransportOption elements, like so:</dt>
68          *  <dd>&lt;TransportOption provider="CURL" option="150"&gt;0&lt;/TransportOption&gt;</dd>
69          * </dl>
70          * 
71          * @param e         DOM to supply configuration
72          * @param cacheTag  optional pointer to string used for cache management
73          */
74         CurlURLInputStream(const xercesc::DOMElement* e, std::string* cacheTag=NULL);
75
76         ~CurlURLInputStream();
77
78 #ifdef XMLTOOLING_XERCESC_64BITSAFE
79         XMLFilePos
80 #else
81         unsigned int
82 #endif
83         curPos() const {
84             return fTotalBytesRead;
85         }
86
87 #ifdef XMLTOOLING_XERCESC_INPUTSTREAM_HAS_CONTENTTYPE
88         const XMLCh* getContentType() const {
89             return fContentType;
90         }
91 #endif
92
93         xsecsize_t readBytes(XMLByte* const toFill, const xsecsize_t maxToRead);
94
95     private :
96         CurlURLInputStream(const CurlURLInputStream&);
97         CurlURLInputStream& operator=(const CurlURLInputStream&);
98
99         // libcurl callbacks for data read/write
100         static size_t staticWriteCallback(char *buffer, size_t size, size_t nitems, void *outstream);
101         size_t writeCallback(char *buffer, size_t size, size_t nitems);
102
103         void init(const xercesc::DOMElement* e=NULL);
104         bool readMore(int *runningHandles);
105
106         logging::Category&  fLog;
107         std::string*        fCacheTag;
108         std::string         fURL;
109         std::vector<std::string>    fSavedOptions;
110
111         CURLM*              fMulti;
112         CURL*               fEasy;
113         struct curl_slist*  fHeaders;
114
115         unsigned long       fTotalBytesRead;
116         XMLByte*            fWritePtr;
117         xsecsize_t          fBytesRead;
118         xsecsize_t          fBytesToRead;
119         bool                fDataAvailable;
120
121         // Overflow buffer for when curl writes more data to us
122         // than we've asked for.
123         XMLByte             fBuffer[CURL_MAX_WRITE_SIZE];
124         XMLByte*            fBufferHeadPtr;
125         XMLByte*            fBufferTailPtr;
126
127         XMLCh*              fContentType;
128         long                fStatusCode;
129
130         char                fError[CURL_ERROR_SIZE];
131     };
132 };
133
134 #endif // __xmltooling_curlinstr_h__