31 PT(HTTPClient) HTTPClient::_global_ptr;
37 trim_blanks(
const string &str) {
39 while (start < str.length() && isspace(str[start])) {
43 size_t end = str.length();
44 while (end > start && isspace(str[end - 1])) {
48 return str.substr(start, end - start);
61 tokenize(
const string &str, vector_string &words,
const string &delimiters) {
63 while (p < str.length()) {
64 size_t q = str.find_first_of(delimiters, p);
65 if (q == string::npos) {
66 words.push_back(str.substr(p));
69 words.push_back(str.substr(p, q - p));
72 words.push_back(
string());
81 ssl_msg_callback(
int write_p,
int version,
int content_type,
82 const void *,
size_t len, SSL *,
void *) {
83 std::ostringstream describe;
87 describe <<
"received ";
91 describe <<
"SSL 2.0 ";
95 describe <<
"SSL 3.0 ";
99 describe <<
"TLS 1.0 ";
103 describe <<
"unknown protocol ";
106 describe <<
"message: ";
108 if (version != SSL2_VERSION) {
109 switch (content_type) {
111 describe <<
"change cipher spec, ";
115 describe <<
"alert, ";
119 describe <<
"handshake, ";
123 describe <<
"application data, ";
127 describe <<
"unknown content type, ";
131 describe << len <<
" bytes.\n";
133 downloader_cat.debug() << describe.str();
135 #endif // !defined(NDEBUG) 144 PRC_DESC(
"Configure this true (the default) to insist on verifying all SSL " 145 "(e.g. https) servers against a known certificate, or false to allow " 146 "an unverified connection. This controls the default behavior; the " 147 "specific behavior for a particular HTTPClient can be adjusted at " 148 "runtime with set_verify_ssl()."));
151 (
"ssl-cipher-list",
"DEFAULT",
152 PRC_DESC(
"This is the default value for HTTPClient::set_cipher_list()."));
156 PRC_DESC(
"This specifies the default value for HTTPClient::set_proxy_spec(). " 157 "It is a semicolon-delimited list of proxies that we use to contact " 158 "all HTTP hosts that don't specify otherwise. See " 159 "set_proxy_spec() for more information."));
162 (
"http-direct-hosts",
"",
163 PRC_DESC(
"This specifies the default value for HTTPClient::set_direct_host_spec(). " 164 "It is a semicolon-delimited list of host names that do not require a " 165 "proxy. See set_direct_host_spec() for more information."));
168 (
"http-try-all-direct",
true,
169 PRC_DESC(
"This specifies the default value for HTTPClient::set_try_all_direct(). " 170 "If this is true, a direct connection will always be attempted after an " 171 "attempt to connect through a proxy fails."));
174 (
"http-proxy-username",
"",
175 PRC_DESC(
"This specifies a default username:password to pass to the proxy."));
179 PRC_DESC(
"Adds one or more username/password pairs to all HTTP clients. The client " 180 "will present this username/password when asked to authenticate a request " 181 "for a particular server and/or realm. The username is of the form " 182 "server:realm:username:password, where either or both of server and " 183 "realm may be empty, or just realm:username:password or username:password. " 184 "If the server or realm is empty, they will match anything."));
187 (
"http-client-certificate-filename",
"",
188 PRC_DESC(
"This provides a default client certificate to offer up should an " 189 "SSL server demand one. The file names a PEM-formatted file " 190 "that includes a public and private key specification. A " 191 "connection-specific certificate may also be specified at runtime on " 192 "the HTTPClient object, but this will require having a different " 193 "HTTPClient object for each differently-certificated connection."));
196 (
"http-client-certificate-passphrase",
"",
197 PRC_DESC(
"This specifies the passphrase to use to decode the certificate named " 198 "by http-client-certificate-filename."));
202 (
"http-preapproved-server-certificate-filename",
203 PRC_DESC(
"This specifies a server hostname:port combination, followed by " 204 "at least one space, and the name of a PEM file that contains " 205 "an SSL certificate that we expect this server to offer. If " 206 "it does, we will accept the cert without further question, " 207 "even if the cert does not match any known certificate " 208 "authorities. This option may appear multiple times."));
211 (
"http-preapproved-server-certificate-name",
212 PRC_DESC(
"This specifies a server hostname:port combination, followed by " 213 "at least one space, and a string describing the subject name " 214 "of an SSL certificate we expect this server to offer. If it " 215 "it does, we will accept the cert, but only if it also matches " 216 "a known certificate authority. This option may appear " 219 _http_version = HTTPEnum::HV_11;
220 _verify_ssl = verify_ssl ? VS_normal : VS_no_verify;
223 set_proxy_spec(http_proxy);
224 set_direct_host_spec(http_direct_hosts);
225 _try_all_direct = http_try_all_direct;
227 if (!http_proxy_username.empty()) {
228 set_username(
"*proxy",
"", http_proxy_username);
231 set_cipher_list(ssl_cipher_list);
235 int num_unique_values = http_username.get_num_unique_values();
236 for (
int i = 0; i < num_unique_values; i++) {
237 string username = http_username.get_unique_value(i);
238 add_http_username(username);
242 _client_certificate_filename = http_client_certificate_filename;
243 _client_certificate_passphrase = http_client_certificate_passphrase;
245 _client_certificate_loaded =
false;
246 _client_certificate_pub =
nullptr;
247 _client_certificate_priv =
nullptr;
249 int num_server_certs = http_preapproved_server_certificate_filename.get_num_unique_values();
251 for (si = 0; si < num_server_certs; si++) {
252 string cert_line = http_preapproved_server_certificate_filename.get_unique_value(si);
254 split_whitespace(a, b, cert_line);
255 add_preapproved_server_certificate_filename(
URLSpec(a,
true), b);
258 num_server_certs = http_preapproved_server_certificate_name.get_num_unique_values();
259 for (si = 0; si < num_server_certs; si++) {
260 string cert_line = http_preapproved_server_certificate_name.get_unique_value(si);
262 split_whitespace(a, b, cert_line);
263 add_preapproved_server_certificate_name(
URLSpec(a,
true), b);
268 OpenSSLWrapper::get_global_ptr();
275 HTTPClient(
const HTTPClient ©) {
285 operator = (
const HTTPClient ©) {
286 _proxies_by_scheme = copy._proxies_by_scheme;
287 _direct_hosts = copy._direct_hosts;
288 _try_all_direct = copy._try_all_direct;
289 _http_version = copy._http_version;
290 _verify_ssl = copy._verify_ssl;
291 _usernames = copy._usernames;
292 _cookies = copy._cookies;
300 if (_ssl_ctx !=
nullptr) {
301 #if OPENSSL_VERSION_NUMBER < 0x10100000 305 _ssl_ctx->cert_store =
nullptr;
307 SSL_CTX_free(_ssl_ctx);
310 unload_client_certificate();
328 OpenSSLWrapper::get_global_ptr();
341 set_proxy_spec(
const string &proxy_spec) {
344 string trim_proxy_spec = trim_blanks(proxy_spec);
347 if (!trim_proxy_spec.empty()) {
348 vector_string proxies;
349 tokenize(trim_proxy_spec, proxies,
";");
351 for (vector_string::const_iterator pi = proxies.begin();
354 const string &spec = (*pi);
359 size_t equals = spec.find(
'=');
360 if (equals == string::npos) {
362 proxy = trim_blanks(spec);
364 scheme = trim_blanks(spec.substr(0, equals));
365 proxy = trim_blanks(spec.substr(equals + 1));
368 if (proxy ==
"DIRECT" || proxy.empty()) {
371 add_proxy(scheme,
URLSpec(proxy,
true));
385 get_proxy_spec()
const {
388 ProxiesByScheme::const_iterator si;
389 for (si = _proxies_by_scheme.begin(); si != _proxies_by_scheme.end(); ++si) {
390 const string &scheme = (*si).first;
391 const Proxies &proxies = (*si).second;
392 Proxies::const_iterator pi;
393 for (pi = proxies.begin(); pi != proxies.end(); ++pi) {
395 if (!result.empty()) {
398 if (!scheme.empty()) {
419 set_direct_host_spec(
const string &direct_host_spec) {
424 tokenize(direct_host_spec, hosts,
";");
426 for (vector_string::const_iterator hi = hosts.begin();
429 string spec = trim_blanks(*hi);
435 add_direct_host(spec);
446 get_direct_host_spec()
const {
449 DirectHosts::const_iterator si;
450 for (si = _direct_hosts.begin(); si != _direct_hosts.end(); ++si) {
453 if (!result.empty()) {
468 _proxies_by_scheme.clear();
478 add_proxy(
const string &scheme,
const URLSpec &proxy) {
483 lc_scheme.reserve(scheme.length());
484 string::const_iterator si;
485 for (si = scheme.begin(); si != scheme.end(); ++si) {
486 lc_scheme += tolower(*si);
490 if (!lc_scheme.empty() && lc_scheme[lc_scheme.length() - 1] ==
':') {
491 lc_scheme = lc_scheme.substr(0, lc_scheme.length() - 1);
494 if (!proxy_url.empty()) {
500 if (lc_scheme ==
"socks") {
503 proxy_url.set_scheme(
"socks");
505 }
else if (!proxy_url.has_scheme()) {
508 proxy_url.set_scheme(
"http");
512 _proxies_by_scheme[lc_scheme].push_back(proxy_url);
521 clear_direct_host() {
522 _direct_hosts.clear();
531 add_direct_host(
const string &hostname) {
534 lc_hostname.reserve(hostname.length());
535 for (string::const_iterator si = hostname.begin();
536 si != hostname.end();
538 lc_hostname += tolower(*si);
560 if (!hostname.empty()) {
561 DirectHosts::const_iterator si;
562 for (si = _direct_hosts.begin(); si != _direct_hosts.end(); ++si) {
563 if ((*si).matches(hostname)) {
577 bool got_any =
false;
579 if (!scheme.empty()) {
581 if (get_proxies_for_scheme(scheme, temp_list)) {
586 if (!got_any && (scheme.empty() || url.
is_ssl())) {
591 if (get_proxies_for_scheme(
"socks", temp_list)) {
594 if (get_proxies_for_scheme(
"https", temp_list)) {
602 if (get_proxies_for_scheme(
"", temp_list)) {
607 if (_try_all_direct) {
609 temp_list.push_back(
URLSpec());
614 get_proxies_for_scheme(
"http", temp_list);
620 for (pi = temp_list.begin(); pi != temp_list.end(); ++pi) {
621 if (used.insert(*pi).second) {
623 proxies.push_back(*pi);
634 get_proxies_for_url(
const URLSpec &url)
const {
636 get_proxies_for_url(url, proxies);
639 if (!proxies.empty()) {
641 if ((*pi).get_url().empty()) {
644 result += (*pi).get_url();
648 while (pi != proxies.end()) {
650 if ((*pi).get_url().empty()) {
653 result += (*pi).get_url();
672 set_username(
const string &server,
const string &realm,
const string &username) {
673 string key = server +
":" + realm;
674 if (username.empty()) {
675 _usernames.erase(key);
677 _usernames[key] = username;
686 get_username(
const string &server,
const string &realm)
const {
687 string key = server +
":" + realm;
688 Usernames::const_iterator ui;
689 ui = _usernames.find(key);
690 if (ui != _usernames.end()) {
701 set_cookie(
const HTTPCookie &cookie) {
702 if (cookie.is_expired()) {
703 clear_cookie(cookie);
706 std::pair<Cookies::iterator, bool> result = _cookies.insert(cookie);
707 if (!result.second) {
710 const HTTPCookie &orig_cookie = *result.first;
711 ((HTTPCookie &)orig_cookie).update_from(cookie);
722 clear_cookie(
const HTTPCookie &cookie) {
723 Cookies::iterator ci = _cookies.find(cookie);
724 if (ci != _cookies.end()) {
736 clear_all_cookies() {
745 has_cookie(
const HTTPCookie &cookie)
const {
746 Cookies::const_iterator ci = _cookies.find(cookie);
747 return (ci != _cookies.end());
754 HTTPCookie HTTPClient::
755 get_cookie(
const HTTPCookie &cookie)
const {
756 Cookies::const_iterator ci = _cookies.find(cookie);
757 if (ci != _cookies.end()) {
770 copy_cookies_from(
const HTTPClient &other) {
771 Cookies::const_iterator ci;
772 for (ci = other._cookies.begin(); ci != other._cookies.end(); ++ci) {
783 write_cookies(std::ostream &out)
const {
784 Cookies::const_iterator ci;
785 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) {
796 send_cookies(std::ostream &out,
const URLSpec &url) {
798 bool any_expired =
false;
799 bool first_cookie =
true;
801 Cookies::const_iterator ci;
802 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) {
803 const HTTPCookie &cookie = (*ci);
804 if (cookie.is_expired(now)) {
807 }
else if (cookie.matches_url(url)) {
810 first_cookie =
false;
814 out << cookie.get_name() <<
"=" << cookie.get_value();
824 Cookies::const_iterator ci;
825 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) {
826 const HTTPCookie &cookie = (*ci);
827 if (!cookie.is_expired(now)) {
828 new_cookies.insert(new_cookies.end(), cookie);
831 _cookies.swap(new_cookies);
844 load_client_certificate() {
845 if (!_client_certificate_loaded) {
846 _client_certificate_loaded =
true;
848 if (!_client_certificate_filename.empty()) {
849 _client_certificate_filename.set_text();
854 if (!vfs->read_file(_client_certificate_filename,
855 _client_certificate_pem,
true)) {
857 downloader_cat.warning()
858 <<
"Could not read " << _client_certificate_filename <<
".\n";
863 if (!_client_certificate_pem.empty()) {
866 BIO *mbio = BIO_new_mem_buf((
void *)_client_certificate_pem.data(),
867 _client_certificate_pem.length());
870 _client_certificate_priv =
871 PEM_read_bio_PrivateKey(mbio,
nullptr,
nullptr,
872 (
char *)_client_certificate_passphrase.c_str());
876 (void)BIO_reset(mbio);
879 _client_certificate_pub =
880 PEM_read_bio_X509(mbio,
nullptr,
nullptr,
nullptr);
885 NotifySeverity sev = NS_debug;
886 string source =
"memory";
887 if (!_client_certificate_filename.empty()) {
892 source = _client_certificate_filename;
895 if (downloader_cat.is_on(sev)) {
896 if (_client_certificate_priv !=
nullptr &&
897 _client_certificate_pub !=
nullptr) {
898 downloader_cat.out(sev)
899 <<
"Read client certificate from " << source <<
"\n";
902 if (_client_certificate_priv ==
nullptr) {
903 downloader_cat.out(sev)
904 <<
"Could not read private key from " << source <<
"\n";
907 if (_client_certificate_pub ==
nullptr) {
908 downloader_cat.out(sev)
909 <<
"Could not read public key from " << source <<
"\n";
916 return (_client_certificate_priv !=
nullptr &&
917 _client_certificate_pub !=
nullptr);
933 add_preapproved_server_certificate_filename(
const URLSpec &url,
const Filename &filename) {
937 if (!vfs->read_file(filename, pem,
true)) {
939 downloader_cat.warning()
940 <<
"Could not read " << filename <<
".\n";
944 return add_preapproved_server_certificate_pem(url, pem);
960 add_preapproved_server_certificate_pem(
const URLSpec &url,
const string &pem) {
963 BIO *mbio = BIO_new_mem_buf((
void *)pem.data(), pem.length());
966 X509 *cert = PEM_read_bio_X509(mbio,
nullptr,
nullptr,
nullptr);
969 if (cert ==
nullptr) {
970 downloader_cat.warning()
971 <<
"Could not parse PEM data\n";
976 PreapprovedServerCerts::iterator psci =
977 _preapproved_server_certs.insert(PreapprovedServerCerts::value_type(server_and_port, PreapprovedServerCert())).first;
979 PreapprovedServerCert &psc = (*psci).second;
980 psc._certs.push_back(cert);
1006 add_preapproved_server_certificate_name(
const URLSpec &url,
const string &name) {
1007 X509_NAME *cert_name = parse_x509_name(name);
1008 if (cert_name ==
nullptr) {
1009 downloader_cat.warning()
1010 <<
"Could not parse certificate name " << name <<
"\n";
1015 PreapprovedServerCerts::iterator psci =
1016 _preapproved_server_certs.insert(PreapprovedServerCerts::value_type(server_and_port, PreapprovedServerCert())).first;
1018 PreapprovedServerCert &psc = (*psci).second;
1019 psc._cert_names.push_back(cert_name);
1029 clear_preapproved_server_certificates(
const URLSpec &url) {
1031 _preapproved_server_certs.erase(server_and_port);
1038 clear_all_preapproved_server_certificates() {
1039 _preapproved_server_certs.clear();
1047 get_http_version_string()
const {
1048 switch (_http_version) {
1049 case HTTPEnum::HV_09:
1052 case HTTPEnum::HV_10:
1055 case HTTPEnum::HV_11:
1058 case HTTPEnum::HV_other:
1071 HTTPEnum::HTTPVersion HTTPClient::
1072 parse_http_version_string(
const string &version) {
1073 if (version ==
"HTTP/1.0") {
1074 return HTTPEnum::HV_10;
1075 }
else if (version ==
"HTTP/1.1") {
1076 return HTTPEnum::HV_11;
1077 }
else if (version.substr(0, 6) ==
"HTTP/0") {
1078 return HTTPEnum::HV_09;
1080 return HTTPEnum::HV_other;
1091 load_certificates(
const Filename &filename) {
1092 OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
1093 return (sslw->load_certificates(filename) != 0);
1111 PT(HTTPChannel) HTTPClient::
1112 make_channel(
bool persistent_connection) {
1113 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1114 doc->set_persistent_connection(persistent_connection);
1124 PT(HTTPChannel) HTTPClient::
1125 post_form(
const URLSpec &url,
const string &body) {
1126 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1127 doc->post_form(url, body);
1136 PT(HTTPChannel) HTTPClient::
1137 get_document(
const URLSpec &url) {
1138 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1139 doc->get_document(url);
1149 PT(HTTPChannel) HTTPClient::
1150 get_header(
const URLSpec &url) {
1151 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1152 doc->get_header(url);
1159 HTTPClient *HTTPClient::
1161 if (_global_ptr ==
nullptr) {
1162 _global_ptr =
new HTTPClient;
1171 SSL_CTX *HTTPClient::
1173 if (_ssl_ctx !=
nullptr) {
1179 _ssl_ctx = SSL_CTX_new(SSLv23_client_method());
1184 if (downloader_cat.is_debug()) {
1185 SSL_CTX_set_msg_callback(_ssl_ctx, ssl_msg_callback);
1190 OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
1191 sslw->notify_ssl_errors();
1193 X509_STORE *store = sslw->get_x509_store();
1194 #if OPENSSL_VERSION_NUMBER >= 0x10100000 1195 if (store !=
nullptr) {
1196 X509_STORE_up_ref(store);
1199 SSL_CTX_set_cert_store(_ssl_ctx, store);
1220 check_preapproved_server_certificate(
const URLSpec &url, X509 *cert,
1221 bool &cert_preapproved,
bool &cert_name_preapproved)
const {
1222 cert_preapproved =
false;
1223 cert_name_preapproved =
false;
1226 PreapprovedServerCerts::const_iterator psci =
1227 _preapproved_server_certs.find(server_and_port);
1229 if (psci == _preapproved_server_certs.end()) {
1234 const PreapprovedServerCert &psc = (*psci).second;
1237 ServerCerts::const_iterator sci;
1238 for (sci = psc._certs.begin(); sci != psc._certs.end(); ++sci) {
1239 if (X509_cmp(cert, *sci) == 0) {
1240 cert_preapproved =
true;
1241 cert_name_preapproved =
true;
1242 downloader_cat.info()
1243 <<
"Server certificate is pre-approved.\n";
1249 X509_NAME *subject = X509_get_subject_name(cert);
1250 ServerCertNames::const_iterator scni;
1251 for (scni = psc._cert_names.begin(); scni != psc._cert_names.end(); ++scni) {
1252 X509_NAME *cert_name = (*scni);
1253 if (x509_name_subset(cert_name, subject)) {
1254 downloader_cat.info()
1255 <<
"Server certificate name is pre-approved.\n";
1256 cert_name_preapproved =
true;
1270 get_proxies_for_scheme(
const string &scheme,
pvector<URLSpec> &proxies)
const {
1271 ProxiesByScheme::const_iterator si = _proxies_by_scheme.find(scheme);
1272 if (si == _proxies_by_scheme.end()) {
1275 const Proxies &scheme_proxies = (*si).second;
1276 if (scheme_proxies.empty()) {
1280 Proxies::const_iterator pi;
1281 for (pi = scheme_proxies.begin(); pi != scheme_proxies.end(); ++pi) {
1282 proxies.push_back(*pi);
1294 add_http_username(
const string &http_username) {
1295 size_t c1 = http_username.find(
':');
1296 if (c1 != string::npos) {
1297 size_t c2 = http_username.find(
':', c1 + 1);
1298 if (c2 != string::npos) {
1299 size_t c3 = http_username.find(
':', c2 + 1);
1300 if (c3 != string::npos) {
1301 size_t c4 = http_username.find(
':', c3 + 1);
1302 if (c4 != string::npos) {
1304 downloader_cat.error()
1305 <<
"Invalid http-username " << http_username <<
"\n";
1309 set_username(http_username.substr(0, c1),
1310 http_username.substr(c1 + 1, c2 - (c1 + 1)),
1311 http_username.substr(c2 + 1));
1316 set_username(
string(),
1317 http_username.substr(0, c1),
1318 http_username.substr(c1 + 1));
1322 set_username(
string(),
string(), http_username);
1326 downloader_cat.error()
1327 <<
"Invalid http-username " << http_username <<
"\n";
1335 select_username(
const URLSpec &url,
bool is_proxy,
const string &realm)
const {
1348 if (username.empty()) {
1350 username = get_username(
"*proxy", realm);
1352 if (username.empty()) {
1354 username = get_username(
"*proxy",
string());
1357 if (username.empty()) {
1359 username = get_username(url.
get_server(), realm);
1361 if (username.empty()) {
1363 username = get_username(url.
get_server(), string());
1365 if (username.empty()) {
1367 username = get_username(
string(), realm);
1369 if (username.empty()) {
1371 username = get_username(
string(),
string());
1381 HTTPAuthorization *HTTPClient::
1382 select_auth(
const URLSpec &url,
bool is_proxy,
const string &last_realm) {
1383 Domains &domains = is_proxy ? _proxy_domains : _www_domains;
1384 string canon = HTTPAuthorization::get_canonical_url(url).get_url();
1388 Domains::const_iterator best_di = domains.end();
1389 size_t longest_length = 0;
1390 Domains::const_iterator di;
1391 for (di = domains.begin(); di != domains.end(); ++di) {
1392 const string &domain = (*di).first;
1393 size_t length = domain.length();
1394 if (domain == canon.substr(0, length)) {
1396 if (length > longest_length) {
1398 longest_length = length;
1403 if (best_di != domains.end()) {
1405 if (downloader_cat.is_spam()) {
1406 downloader_cat.spam()
1407 <<
"Choosing domain " << (*best_di).first <<
" for " << url <<
"\n";
1409 const Realms &realms = (*best_di).second._realms;
1411 Realms::const_iterator ri;
1412 ri = realms.find(last_realm);
1413 if (ri != realms.end()) {
1414 return (*ri).second;
1417 if (!realms.empty()) {
1419 return (*realms.begin()).second;
1433 PT(HTTPAuthorization) HTTPClient::
1434 generate_auth(
const URLSpec &url,
bool is_proxy,
const string &challenge) {
1435 HTTPAuthorization::AuthenticationSchemes schemes;
1436 HTTPAuthorization::parse_authentication_schemes(schemes, challenge);
1438 PT(HTTPAuthorization) auth;
1439 HTTPAuthorization::AuthenticationSchemes::iterator si;
1441 si = schemes.find(
"digest");
1442 if (si != schemes.end()) {
1443 auth =
new HTTPDigestAuthorization((*si).second, url, is_proxy);
1446 if (auth ==
nullptr || !auth->is_valid()) {
1447 si = schemes.find(
"basic");
1448 if (si != schemes.end()) {
1449 auth =
new HTTPBasicAuthorization((*si).second, url, is_proxy);
1453 if (auth ==
nullptr || !auth->is_valid()) {
1454 downloader_cat.warning()
1455 <<
"Don't know how to use any of the server's available authorization schemes:\n";
1456 for (si = schemes.begin(); si != schemes.end(); ++si) {
1457 downloader_cat.warning() << (*si).first <<
"\n";
1463 Domains &domains = is_proxy ? _proxy_domains : _www_domains;
1464 const vector_string &domain = auth->get_domain();
1465 vector_string::const_iterator si;
1466 for (si = domain.begin(); si != domain.end(); ++si) {
1467 domains[(*si)]._realms[auth->get_realm()] = auth;
1479 unload_client_certificate() {
1480 if (_client_certificate_priv !=
nullptr) {
1481 EVP_PKEY_free(_client_certificate_priv);
1482 _client_certificate_priv =
nullptr;
1485 if (_client_certificate_pub !=
nullptr) {
1486 X509_free(_client_certificate_pub);
1487 _client_certificate_pub =
nullptr;
1490 _client_certificate_loaded =
false;
1497 X509_NAME *HTTPClient::
1498 parse_x509_name(
const string &source) {
1499 X509_NAME *result =
nullptr;
1501 result = X509_NAME_new();
1502 bool added_any =
false;
1504 string::const_iterator si;
1505 si = source.begin();
1506 while (si != source.end()) {
1512 while (si != source.end() && (*si) !=
'=' && (*si) !=
'/') {
1513 if ((*si) ==
'\\') {
1515 if (si != source.end()) {
1525 int nid = OBJ_txt2nid((
char *)type.c_str());
1526 if (nid == NID_undef) {
1527 downloader_cat.info()
1528 <<
"Unknown type " << type <<
" in X509 name: " << source
1530 X509_NAME_free(result);
1536 if (si != source.end() && (*si) ==
'=') {
1538 while (si != source.end() && (*si) !=
'/') {
1539 if ((*si) ==
'\\') {
1541 if (si != source.end()) {
1552 if (!value.empty()) {
1554 X509_NAME_add_entry_by_NID(result, nid, V_ASN1_APP_CHOOSE,
1555 (
unsigned char *)value.c_str(), -1, -1, 0);
1557 downloader_cat.info()
1558 <<
"Unable to add " << type <<
"=" << value <<
" in X509 name: " 1560 X509_NAME_free(result);
1569 downloader_cat.info()
1570 <<
"Invalid empty X509 name: " << source <<
"\n";
1571 X509_NAME_free(result);
1583 x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) {
1584 int count_a = X509_NAME_entry_count(name_a);
1585 for (
int ai = 0; ai < count_a; ai++) {
1586 X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai);
1588 int bi = X509_NAME_get_index_by_OBJ(name_b, X509_NAME_ENTRY_get_object(na), -1);
1594 X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi);
1595 ASN1_STRING *na_value = X509_NAME_ENTRY_get_data(na);
1596 ASN1_STRING *nb_value = X509_NAME_ENTRY_get_data(nb);
1597 if (na_value->length != nb_value->length ||
1598 memcmp(na_value->data, nb_value->data, na_value->length) != 0) {
1610 split_whitespace(
string &a,
string &b,
const string &c) {
1614 while (p < c.length() && isspace(c[p])) {
1620 while (p < c.length() && !isspace(c[p])) {
1624 a = c.substr(q, p - q);
1627 while (p < c.length() && isspace(c[p])) {
1636 HTTPClient::PreapprovedServerCert::
1637 ~PreapprovedServerCert() {
1638 ServerCerts::const_iterator sci;
1639 for (sci = _certs.begin(); sci != _certs.end(); ++sci) {
1643 ServerCertNames::const_iterator scni;
1644 for (scni = _cert_names.begin(); scni != _cert_names.end(); ++scni) {
1645 X509_NAME_free(*scni);
1649 #endif // HAVE_OPENSSL is_ssl
Returns true if the URL's scheme specifies an SSL-secured protocol such as https, or false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for a URL, e.g.
This is a convenience class to specialize ConfigVariable as a Filename type.
A hierarchy of directories and files that appears to be one continuous file system,...
This is a convenience class to specialize ConfigVariable as a boolean type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool has_username() const
Returns true if the URL specifies a username (and/or password), false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool empty() const
Returns false if the URLSpec is valid (not empty), or true if it is an empty string.
This class is similar to ConfigVariable, but it reports its value as a list of strings.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
get_scheme
Returns the scheme specified by the URL, or empty string if no scheme is specified.
The name of a file, such as a texture file or an Egg file.
This is a convenience class to specialize ConfigVariable as a string type.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
A container for an HTTP-legal time/date indication.
static HTTPDate now()
Returns an HTTPDate that represents the current time and date.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_pattern
Returns the pattern string that the GlobPattern object matches.
void tokenize(const string &str, vector_string &words, const string &delimiters, bool discard_repeated_delimiters)
Chops the source string up into pieces delimited by any of the characters specified in delimiters.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const std::string & get_url() const
Returns the complete URL specification.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_server
Returns the server name specified by the URL, if any.
get_username
Returns the username specified by the URL, if any.
This is our own Panda specialization on the default STL set.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_server_and_port
Returns a string consisting of the server name, followed by a colon, followed by the port number.
This class can be used to test for string matches against standard Unix- shell filename globbing conv...