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