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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <curl/curl.h>
26 #include <xercesc/util/XercesDefs.hpp>
27 #include <xercesc/util/XMLNetAccessor.hpp>
28 #include <xercesc/util/XMLString.hpp>
29 #include <xercesc/util/XMLExceptMsgs.hpp>
30 #include <xercesc/util/Janitor.hpp>
31 #include <xercesc/util/XMLUniDefs.hpp>
32 #include <xercesc/util/TransService.hpp>
33 #include <xercesc/util/TranscodingException.hpp>
34 #include <xercesc/util/PlatformUtils.hpp>
36 #include <xmltooling/util/CurlURLInputStream.hpp>
38 using namespace xmltooling;
41 CurlURLInputStream::CurlURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
42 : fMemoryManager(urlSource.getMemoryManager())
43 , fURLSource(urlSource)
46 , m_log(logging::Category::getInstance(XMLTOOLING_LOGCAT".libcurl.NetAccessor"))
48 // Get the text of the URL we're going to use
49 fURL.reset(XMLString::transcode(fURLSource.getURLText(), fMemoryManager), fMemoryManager);
53 CurlURLInputStream::~CurlURLInputStream()
59 size_t CurlURLInputStream::staticWriteCallback(void* ptr, size_t size, size_t nmemb, void* stream)
61 size_t len = size*nmemb;
62 reinterpret_cast<std::stringstream*>(stream)->write(reinterpret_cast<const char*>(ptr),len);
67 unsigned int CurlURLInputStream::readBytes(XMLByte* const toFill, const unsigned int maxToRead)
70 // Allocate the curl easy handle.
71 CURL* fEasy = curl_easy_init();
73 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_InternalError, "unable to allocate libcurl handle", fMemoryManager);
75 m_log.debug("libcurl trying to fetch %s", fURL.get());
78 curl_easy_setopt(fEasy, CURLOPT_URL, fURL.get());
79 curl_easy_setopt(fEasy, CURLOPT_WRITEDATA, &fUnderlyingStream);
80 curl_easy_setopt(fEasy, CURLOPT_WRITEFUNCTION, staticWriteCallback);
81 curl_easy_setopt(fEasy, CURLOPT_CONNECTTIMEOUT, 30);
82 curl_easy_setopt(fEasy, CURLOPT_TIMEOUT, 60);
83 curl_easy_setopt(fEasy, CURLOPT_SSL_VERIFYHOST, 0);
84 curl_easy_setopt(fEasy, CURLOPT_SSL_VERIFYPEER, 0);
85 curl_easy_setopt(fEasy, CURLOPT_NOPROGRESS, 1);
86 curl_easy_setopt(fEasy, CURLOPT_NOSIGNAL, 1);
87 curl_easy_setopt(fEasy, CURLOPT_FAILONERROR, 1);
89 char curl_errorbuf[CURL_ERROR_SIZE];
91 curl_easy_setopt(fEasy,CURLOPT_ERRORBUFFER,curl_errorbuf);
94 if (curl_easy_perform(fEasy) != CURLE_OK) {
95 curl_easy_cleanup(fEasy);
96 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_InternalError, curl_errorbuf, fMemoryManager);
99 curl_easy_cleanup(fEasy);
102 switch (msg->data.result)
105 // We completed successfully. runningHandles should have dropped to zero, so we'll bail out below...
108 case CURLE_UNSUPPORTED_PROTOCOL:
109 ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_UnsupportedProto, fMemoryManager);
112 case CURLE_COULDNT_RESOLVE_HOST:
113 case CURLE_COULDNT_RESOLVE_PROXY:
114 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, fURLSource.getHost(), fMemoryManager);
117 case CURLE_COULDNT_CONNECT:
118 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ConnSocket, fURLSource.getURLText(), fMemoryManager);
120 case CURLE_RECV_ERROR:
121 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, fURLSource.getURLText(), fMemoryManager);
125 m_log.error("curl NetAccessor encountered error from libcurl (%d)", msg->data.result);
126 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_InternalError, fURLSource.getURLText(), fMemoryManager);
131 fInputStream = new (fMemoryManager) StreamInputSource::StreamBinInputStream(fUnderlyingStream);
134 // Defer to the stream wrapper.
135 return fInputStream->readBytes(toFill, maxToRead);