a8b72bac539788bfa894db24c1d6ce28247a639b
[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=nullptr);
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=nullptr);
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=nullptr);
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         /**
96          * Access the OpenSSL context options in place for this object.
97          *
98          * @return bitmask suitable for use with SSL_CTX_set_options
99          */
100         int getOpenSSLOps() const {
101             return fOpenSSLOps;
102         }
103
104     private :
105         CurlURLInputStream(const CurlURLInputStream&);
106         CurlURLInputStream& operator=(const CurlURLInputStream&);
107
108         // libcurl callbacks for data read/write
109         static size_t staticWriteCallback(char *buffer, size_t size, size_t nitems, void *outstream);
110         size_t writeCallback(char *buffer, size_t size, size_t nitems);
111
112         void init(const xercesc::DOMElement* e=nullptr);
113         bool readMore(int *runningHandles);
114
115         logging::Category&  fLog;
116         std::string*        fCacheTag;
117         std::string         fURL;
118         std::vector<std::string>    fSavedOptions;
119         int                 fOpenSSLOps;
120
121         CURLM*              fMulti;
122         CURL*               fEasy;
123         struct curl_slist*  fHeaders;
124
125         unsigned long       fTotalBytesRead;
126         XMLByte*            fWritePtr;
127         xsecsize_t          fBytesRead;
128         xsecsize_t          fBytesToRead;
129         bool                fDataAvailable;
130
131         // Overflow buffer for when curl writes more data to us
132         // than we've asked for.
133         XMLByte*            fBuffer;
134         XMLByte*            fBufferHeadPtr;
135         XMLByte*            fBufferTailPtr;
136         size_t              fBufferSize;
137
138         XMLCh*              fContentType;
139         long                fStatusCode;
140
141         char                fError[CURL_ERROR_SIZE];
142     };
143 };
144
145 #endif // __xmltooling_curlinstr_h__