+void CurlURLInputStream::init(const DOMElement* e)
+{
+ // Allocate the curl multi handle
+ fMulti = curl_multi_init();
+
+ // Allocate the curl easy handle
+ fEasy = curl_easy_init();
+
+ if (!fMulti || !fEasy)
+ throw IOException("Failed to allocate libcurl handles.");
+
+ curl_easy_setopt(fEasy, CURLOPT_URL, fURL.c_str());
+
+ // Set up a way to recieve the data
+ curl_easy_setopt(fEasy, CURLOPT_WRITEDATA, this); // Pass this pointer to write function
+ curl_easy_setopt(fEasy, CURLOPT_WRITEFUNCTION, staticWriteCallback); // Our static write function
+
+ // Do redirects
+ curl_easy_setopt(fEasy, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt(fEasy, CURLOPT_MAXREDIRS, 6);
+
+ // Default settings.
+ curl_easy_setopt(fEasy, CURLOPT_CONNECTTIMEOUT,15);
+ curl_easy_setopt(fEasy, CURLOPT_TIMEOUT,30);
+ curl_easy_setopt(fEasy, CURLOPT_HTTPAUTH,0);
+ curl_easy_setopt(fEasy, CURLOPT_USERPWD,NULL);
+ curl_easy_setopt(fEasy, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_easy_setopt(fEasy, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(fEasy, CURLOPT_SSL_CIPHER_LIST, "ALL:!aNULL:!LOW:!EXPORT:!SSLv2");
+ curl_easy_setopt(fEasy, CURLOPT_NOPROGRESS, 1);
+ curl_easy_setopt(fEasy, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(fEasy, CURLOPT_FAILONERROR, 1);
+
+ fError[0] = 0;
+ curl_easy_setopt(fEasy, CURLOPT_ERRORBUFFER, fError);
+
+ if (e) {
+ const XMLCh* flag = e->getAttributeNS(NULL, verifyHost);
+ if (flag && (*flag == chLatin_f || *flag == chDigit_0))
+ curl_easy_setopt(fEasy, CURLOPT_SSL_VERIFYHOST, 2);
+
+ // Process TransportOption elements.
+ bool success;
+ DOMElement* child = XMLHelper::getLastChildElement(e, TransportOption);
+ while (child) {
+ if (child->hasChildNodes() && XMLString::equals(child->getAttributeNS(NULL,_provider), _CURL)) {
+ auto_ptr_char option(child->getAttributeNS(NULL,_option));
+ auto_ptr_char value(child->getFirstChild()->getNodeValue());
+ if (option.get() && *option.get() && value.get() && *value.get()) {
+ // For libcurl, the option is an enum and the value type depends on the option.
+ CURLoption opt = static_cast<CURLoption>(strtol(option.get(), NULL, 10));
+ if (opt < CURLOPTTYPE_OBJECTPOINT)
+ success = (curl_easy_setopt(fEasy, opt, strtol(value.get(), NULL, 10)) == CURLE_OK);
+#ifdef CURLOPTTYPE_OFF_T
+ else if (opt < CURLOPTTYPE_OFF_T)
+ success = (curl_easy_setopt(fEasy, opt, value.get()) == CURLE_OK);
+ else if (sizeof(curl_off_t) == sizeof(long))
+ success = (curl_easy_setopt(fEasy, opt, strtol(value.get(), NULL, 10)) == CURLE_OK);
+ else
+ success = false;
+#else
+ else
+ success = (curl_easy_setopt(fEasy, opt, value.get()) == CURLE_OK);
+#endif
+ if (!success)
+ fLog.error("failed to set transport option (%s)", option.get());
+ }
+ }
+ child = XMLHelper::getPreviousSiblingElement(child, TransportOption);
+ }
+ }
+
+ // Add easy handle to the multi stack
+ curl_multi_add_handle(fMulti, fEasy);
+
+ fLog.debug("libcurl trying to fetch %s", fURL.c_str());
+
+ // Start reading, to get the content type
+ while(fBufferHeadPtr == fBuffer) {
+ int runningHandles = 0;
+ try {
+ readMore(&runningHandles);
+ }
+ catch (XMLException& ex) {
+ curl_multi_remove_handle(fMulti, fEasy);
+ curl_easy_cleanup(fEasy);
+ fEasy = NULL;
+ curl_multi_cleanup(fMulti);
+ fMulti = NULL;
+ auto_ptr_char msg(ex.getMessage());
+ throw IOException(msg.get());
+ }
+ if(runningHandles == 0) break;
+ }