32 #include "GatewayUtils.h"
34 #include "curl_utils.h"
45 #define CLIENT_ERR_MIN 400
46 #define CLIENT_ERR_MAX 417
47 const char *http_client_errors[CLIENT_ERR_MAX - CLIENT_ERR_MIN +1] =
50 "Unauthorized: Contact the server administrator.",
52 "Forbidden: Contact the server administrator.",
53 "Not Found: The data source or server could not be found.\n"
54 "Often this means that the OPeNDAP server is missing or needs attention.\n"
55 "Please contact the server administrator.",
56 "Method Not Allowed.",
58 "Proxy Authentication Required.",
63 "Precondition Failed.",
64 "Request Entity Too Large.",
65 "Request URI Too Large.",
66 "Unsupported Media Type.",
67 "Requested Range Not Satisfiable.",
71 #define SERVER_ERR_MIN 500
72 #define SERVER_ERR_MAX 505
73 const char *http_server_errors[SERVER_ERR_MAX - SERVER_ERR_MIN + 1] =
75 "Internal Server Error.",
78 "Service Unavailable.",
80 "HTTP Version Not Supported."
86 string http_status_to_string(
int status)
88 if (status >= CLIENT_ERR_MIN && status <= CLIENT_ERR_MAX)
89 return string(http_client_errors[status - CLIENT_ERR_MIN]);
90 else if (status >= SERVER_ERR_MIN && status <= SERVER_ERR_MAX)
91 return string(http_server_errors[status - SERVER_ERR_MIN]);
93 return string(
"Unknown Error: This indicates a problem with libdap++.\nPlease report this to support@opendap.org.");
96 static string getCurlAuthTypeName(
const int authType){
98 string authTypeString;
101 match = authType & CURLAUTH_BASIC;
103 authTypeString +=
"CURLAUTH_BASIC";
106 match = authType & CURLAUTH_DIGEST;
108 if(!authTypeString.empty())
109 authTypeString +=
" ";
110 authTypeString +=
"CURLAUTH_DIGEST";
113 match = authType & CURLAUTH_DIGEST_IE;
115 if(!authTypeString.empty())
116 authTypeString +=
" ";
117 authTypeString +=
"CURLAUTH_DIGEST_IE";
120 match = authType & CURLAUTH_GSSNEGOTIATE;
122 if(!authTypeString.empty())
123 authTypeString +=
" ";
124 authTypeString +=
"CURLAUTH_GSSNEGOTIATE";
127 match = authType & CURLAUTH_NTLM;
129 if(!authTypeString.empty())
130 authTypeString +=
" ";
131 authTypeString +=
"CURLAUTH_NTLM";
135 match = authType & CURLAUTH_ANY;
137 if(!authTypeString.empty())
138 authTypeString +=
" ";
139 authTypeString +=
"CURLAUTH_ANY";
143 match = authType & CURLAUTH_ANY;
145 if(!authTypeString.empty())
146 authTypeString +=
" ";
147 authTypeString +=
"CURLAUTH_ANYSAFE";
151 match = authType & CURLAUTH_ANY;
153 if(!authTypeString.empty())
154 authTypeString +=
" ";
155 authTypeString +=
"CURLAUTH_ONLY";
159 return authTypeString;
167 static size_t writeToOpenfileDescriptor(
char *data,
size_t ,
size_t nmemb,
void *userdata){
169 int *fd = (
int *) userdata;
171 BESDEBUG(
"curl",
"curl_utils::writeToOpenfileDescriptor() - Bytes received " << libdap::long_to_string(nmemb) << endl);
172 int wrote = write(*fd, data, nmemb);
173 BESDEBUG(
"curl",
"curl_utils::writeToOpenfileDescriptor() - Bytes written " << libdap::long_to_string(wrote) << endl);
202 static size_t save_raw_http_headers(
void *ptr,
size_t size,
size_t nmemb,
void *resp_hdrs)
204 BESDEBUG(
"curl",
"curl_utils::save_raw_http_headers() - Inside the header parser." << endl);
205 vector<string> *hdrs =
static_cast<vector<string> *
>(resp_hdrs);
208 string complete_line;
209 if (nmemb > 1 && *(
static_cast<char*
>(ptr) + size * (nmemb - 2)) ==
'\r')
210 complete_line.assign(
static_cast<char *
>(ptr), size * (nmemb - 2));
212 complete_line.assign(
static_cast<char *
>(ptr), size * (nmemb - 1));
215 if (complete_line !=
"" && complete_line.find(
"HTTP") == string::npos) {
216 BESDEBUG(
"curl",
"curl_utils::save_raw_http_headers() - Header line: " << complete_line << endl);
217 hdrs->push_back(complete_line);
228 static int curl_debug(CURL *, curl_infotype info,
char *msg,
size_t size,
void *)
230 string message(msg, size);
234 BESDEBUG(
"curl",
"curl_utils::curl_debug() - Text: " << message << endl );
break;
235 case CURLINFO_HEADER_IN:
236 BESDEBUG(
"curl",
"curl_utils::curl_debug() - Header in: " << message << endl );
break;
237 case CURLINFO_HEADER_OUT:
238 BESDEBUG(
"curl",
"curl_utils::curl_debug() - Header out: " << endl << message << endl );
break;
239 case CURLINFO_DATA_IN:
240 BESDEBUG(
"curl",
"curl_utils::curl_debug() - Data in: " << message << endl );
break;
241 case CURLINFO_DATA_OUT:
242 BESDEBUG(
"curl",
"curl_utils::curl_debug() - Data out: " << message << endl );
break;
244 BESDEBUG(
"curl",
"curl_utils::curl_debug() - End: " << message << endl );
break;
245 #ifdef CURLINFO_SSL_DATA_IN
246 case CURLINFO_SSL_DATA_IN:
247 BESDEBUG(
"curl",
"curl_utils::curl_debug() - SSL Data in: " << message << endl );
break;
249 #ifdef CURLINFO_SSL_DATA_OUT
250 case CURLINFO_SSL_DATA_OUT:
251 BESDEBUG(
"curl",
"curl_utils::curl_debug() - SSL Data out: " << message << endl );
break;
254 BESDEBUG(
"curl",
"curl_utils::curl_debug() - Curl info: " << message << endl );
break;
267 class BuildHeaders :
public std::unary_function<const string &, void>
269 struct curl_slist *d_cl;
272 BuildHeaders() : d_cl(0)
275 void operator()(
const string &header)
277 BESDEBUG(
"curl",
"BuildHeaders::operator() - Adding '" << header.c_str() <<
"' to the header list." << endl);
278 d_cl = curl_slist_append(d_cl, header.c_str());
281 struct curl_slist *get_headers()
306 bool configureProxy(CURL *curl,
const string &url) {
307 BESDEBUG(
"curl",
"curl_utils::configureProxy() - BEGIN." << endl);
309 bool using_proxy =
false;
315 string proxyHost = gateway::GatewayUtils::ProxyHost;
316 int proxyPort = gateway::GatewayUtils::ProxyPort;
317 string proxyPassword = gateway::GatewayUtils::ProxyPassword;
318 string proxyUser = gateway::GatewayUtils::ProxyUser;
319 string proxyUserPW = gateway::GatewayUtils::ProxyUserPW;
320 int proxyAuthType = gateway::GatewayUtils::ProxyAuthType;
322 if (!proxyHost.empty()) {
333 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Found proxy configuration." << endl);
339 if (!GatewayUtils::NoProxyRegex.empty()) {
340 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Found NoProxyRegex." << endl);
341 libdap::Regex r(GatewayUtils::NoProxyRegex.c_str());
342 if (r.match(url.c_str(), url.length()) != -1) {
343 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Found NoProxy match. Regex: " << GatewayUtils::NoProxyRegex <<
"; Url: " << url << endl);
350 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Setting up a proxy server." << endl);
351 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Proxy host: " << proxyHost << endl);
352 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Proxy port: " << proxyPort << endl);
354 curl_easy_setopt(curl, CURLOPT_PROXY, proxyHost.data());
355 curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxyPort);
366 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLOPT_PROXYAUTH = " << CURLOPT_PROXYAUTH << endl);
367 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_BASIC = " << CURLAUTH_BASIC << endl);
368 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_DIGEST = " << CURLAUTH_DIGEST << endl);
369 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_DIGEST_IE = " << CURLAUTH_DIGEST_IE << endl);
370 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_GSSNEGOTIATE = " << CURLAUTH_GSSNEGOTIATE << endl);
371 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_NTLM = " << CURLAUTH_NTLM << endl);
372 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_ANY = " << CURLAUTH_ANY << endl);
373 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_ANYSAFE = " << CURLAUTH_ANYSAFE << endl);
374 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLAUTH_ONLY = " << CURLAUTH_ONLY << endl);
375 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Using CURLOPT_PROXYAUTH = " << proxyAuthType << endl);
378 BESDEBUG(
"curl",
"curl_utils::configureProxy() - Using CURLOPT_PROXYAUTH = " << getCurlAuthTypeName(proxyAuthType) << endl);
379 curl_easy_setopt(curl, CURLOPT_PROXYAUTH, proxyAuthType);
384 if (!proxyUser.empty()){
385 curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, proxyUser.data());
386 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLOPT_PROXYUSER : " << proxyUser << endl);
388 if (!proxyPassword.empty()){
389 curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, proxyPassword.data());
390 BESDEBUG(
"curl",
"curl_utils::configureProxy() - CURLOPT_PROXYPASSWORD: " << proxyPassword << endl);
393 else if (!proxyUserPW.empty()){
395 "curl_utils::configureProxy() - CURLOPT_PROXYUSERPWD : " << proxyUserPW << endl);
396 curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxyUserPW.data());
401 BESDEBUG(
"curl",
"curl_utils::configureProxy() - END." << endl);
428 CURL *init(
char *error_buffer)
431 CURL *curl = curl_easy_init();
433 throw libdap::InternalErr(__FILE__, __LINE__,
"Could not initialize libcurl.");
445 #ifndef CURLOPT_ACCEPT_ENCODING
446 curl_easy_setopt(curl, CURLOPT_ENCODING,
"");
448 curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING,
"");
451 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer);
454 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0);
459 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (
long)CURLAUTH_ANY);
461 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
462 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
463 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, save_raw_http_headers);
468 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
469 curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5);
473 curl_easy_setopt(curl, CURLOPT_USERAGENT, curl_version());
478 if (!d_rcr->get_validate_ssl() == 0) {
479 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
480 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
487 if (!d_cookie_jar.empty()) {
488 BESDEBUG(cerr <<
"Setting the cookie jar to: " << d_cookie_jar << endl);
489 curl_easy_setopt(curl, CURLOPT_COOKIEJAR, d_cookie_jar.c_str());
490 curl_easy_setopt(curl, CURLOPT_COOKIESESSION, 1);
496 BESDEBUG(
"curl",
"curl_utils::www_lib_init() - Curl version: " << curl_version() << endl);
497 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
498 BESDEBUG(
"curl",
"curl_utils::www_lib_init() - Curl in verbose mode."<< endl);
499 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug);
500 BESDEBUG(
"curl",
"curl_utils::www_lib_init() - Curl debugging function installed."<< endl);
504 BESDEBUG(
"curl",
"curl_utils::www_lib_init() - curl: " << curl << endl);
529 long read_url(CURL *curl,
532 vector<string> *resp_hdrs,
533 const vector<string> *request_headers,
537 BESDEBUG(
"curl",
"curl_utils::read_url() - BEGIN" << endl);
540 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
542 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeToOpenfileDescriptor);
545 #ifdef CURLOPT_WRITEDATA
546 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fd);
548 curl_easy_setopt(curl, CURLOPT_FILE, &fd);
555 BuildHeaders req_hdrs;
559 req_hdrs = for_each(request_headers->begin(), request_headers->end(), req_hdrs);
560 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, req_hdrs.get_headers());
566 curl_easy_setopt(curl, CURLOPT_WRITEHEADER, resp_hdrs);
569 CURLcode res = curl_easy_perform(curl);
572 curl_slist_free_all(req_hdrs.get_headers());
573 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, 0);
577 BESDEBUG(
"curl",
"curl_utils::read_url() - OUCH! CURL returned an error! curl msg: " << curl_easy_strerror(res) << endl);
578 BESDEBUG(
"curl",
"curl_utils::read_url() - OUCH! CURL returned an error! error_buffer: " << error_buffer << endl);
579 throw libdap::Error(error_buffer);
583 res = curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &status);
584 BESDEBUG(
"curl",
"curl_utils::read_url() - HTTP Status " << status << endl);
586 throw libdap::Error(error_buffer);
587 BESDEBUG(
"curl",
"curl_utils::read_url() - END" << endl);