00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00037
00038 #include "config.h"
00039
00040 #include <cstring>
00041 #include <cstdlib>
00042
00043 #include <unistd.h>
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046
00047 #ifdef WIN32
00048 #define FALSE 0
00049
00050 #define F_OK 0
00051 #define DIR_SEP_STRING "\\"
00052 #define DIR_SEP_CHAR '\\'
00053 #include <direct.h>
00054 #else
00055 #define DIR_SEP_STRING "/"
00056 #define DIR_SEP_CHAR '/'
00057 #endif
00058
00059 #include <pthread.h>
00060
00061 #include <fstream>
00062
00063 #include "debug.h"
00064 #include "RCReader.h"
00065 #include "Error.h"
00066
00067 using namespace std;
00068
00069 namespace libdap {
00070
00071 RCReader* RCReader::_instance = 0;
00072
00073
00074
00075
00076 static pthread_once_t instance_control = PTHREAD_ONCE_INIT;
00077
00082 bool
00083 RCReader::write_rc_file(const string &pathname)
00084 {
00085 DBG(cerr << "Writing the RC file to " << pathname << endl);
00086 ofstream fpo(pathname.c_str());
00087
00088
00089
00090
00091 if (fpo) {
00092
00093
00094 fpo << "# OPeNDAP client configuration file. See the OPeNDAP" << endl;
00095 fpo << "# users guide for information." << endl;
00096 fpo << "USE_CACHE=" << _dods_use_cache << endl;
00097 fpo << "# Cache and object size are given in megabytes (20 ==> 20Mb)."
00098 << endl;
00099 fpo << "MAX_CACHE_SIZE=" << _dods_cache_max << endl;
00100 fpo << "MAX_CACHED_OBJ=" << _dods_cached_obj << endl;
00101 fpo << "IGNORE_EXPIRES=" << _dods_ign_expires << endl;
00102 fpo << "CACHE_ROOT=" << d_cache_root << endl;
00103 fpo << "DEFAULT_EXPIRES=" << _dods_default_expires << endl;
00104 fpo << "ALWAYS_VALIDATE=" << _dods_always_validate << endl;
00105 fpo << "# Request servers compress responses if possible?" << endl;
00106 fpo << "# 1 (yes) or 0 (false)." << endl;
00107 fpo << "DEFLATE=" << _dods_deflate << endl;
00108
00109 fpo << "# Should SSL certificates and hosts be validated? SSL" << endl;
00110 fpo << "# will only work with signed certificates." << endl;
00111 fpo << "VALIDATE_SSL=" << d_validate_ssl << endl;
00112
00113 fpo << "# Proxy configuration (optional parts in []s)." << endl;
00114 fpo << "# You may also use the 'http_proxy' environment variable"
00115 << endl;
00116 fpo << "# but a value in this file will override that env variable."
00117 << endl;
00118 fpo << "# PROXY_SERVER=[http://][username:password@]host[:port]"
00119 << endl;
00120 if (!d_dods_proxy_server_host.empty()) {
00121 fpo << "PROXY_SERVER=" << d_dods_proxy_server_protocol << "://"
00122 << (d_dods_proxy_server_userpw.empty()
00123 ? ""
00124 : d_dods_proxy_server_userpw + "@")
00125 + d_dods_proxy_server_host
00126 + ":" + long_to_string(d_dods_proxy_server_port) << endl;
00127 }
00128
00129 fpo << "# NO_PROXY_FOR=<host|domain>" << endl;
00130 if (!d_dods_no_proxy_for_host.empty()) {
00131 fpo << "NO_PROXY_FOR=" << d_dods_no_proxy_for_host << endl;
00132 }
00133
00134 fpo << "# AIS_DATABASE=<file or url>" << endl;
00135
00136 fpo << "# COOKIE_JAR=.dods_cookies" << endl;
00137 fpo << "# The cookie jar is a file that holds cookies sent from"
00138 << endl;
00139 fpo << "# servers such as single signon systems. Uncomment this"
00140 << endl;
00141 fpo << "# option and provide a file name to activate this feature."
00142 << endl;
00143 fpo << "# If the value is a filename, it will be created in this"
00144 << endl;
00145 fpo << "# directory; a full pathname can be used to force a specific"
00146 << endl;
00147 fpo << "# location." << endl;
00148
00149 fpo.close();
00150 return true;
00151 }
00152
00153 return false;
00154 }
00155
00156 bool
00157 RCReader::read_rc_file(const string &pathname)
00158 {
00159 DBG(cerr << "Reading the RC file from " << pathname << endl);
00160
00161 ifstream fpi(pathname.c_str());
00162 if (fpi) {
00163
00164
00165
00166
00167 char *value;
00168 char *tempstr = new char[1024];;
00169 int tokenlength;
00170 while (true) {
00171 fpi.getline(tempstr, 1023);
00172 if (!fpi.good())
00173 break;
00174
00175 value = strchr(tempstr, '=');
00176 if (!value)
00177 continue;
00178 tokenlength = value - tempstr;
00179 value++;
00180
00181 if ((strncmp(tempstr, "USE_CACHE", 9) == 0)
00182 && tokenlength == 9) {
00183 _dods_use_cache = atoi(value) ? true : false;
00184 }
00185 else if ((strncmp(tempstr, "MAX_CACHE_SIZE", 14) == 0)
00186 && tokenlength == 14) {
00187 _dods_cache_max = atoi(value);
00188 }
00189 else if ((strncmp(tempstr, "MAX_CACHED_OBJ", 14) == 0)
00190 && tokenlength == 14) {
00191 _dods_cached_obj = atoi(value);
00192 }
00193 else if ((strncmp(tempstr, "IGNORE_EXPIRES", 14) == 0)
00194 && tokenlength == 14) {
00195 _dods_ign_expires = atoi(value);
00196 }
00197 else if ((strncmp(tempstr, "DEFLATE", 7) == 0)
00198 && tokenlength == 7) {
00199 _dods_deflate = atoi(value) ? true : false;
00200 }
00201 else if ((strncmp(tempstr, "CACHE_ROOT", 10) == 0)
00202 && tokenlength == 10) {
00203 d_cache_root = value;
00204 if (d_cache_root[d_cache_root.length() - 1] != DIR_SEP_CHAR)
00205 d_cache_root += string(DIR_SEP_STRING);
00206 }
00207 else if ((strncmp(tempstr, "DEFAULT_EXPIRES", 15) == 0)
00208 && tokenlength == 15) {
00209 _dods_default_expires = atoi(value);
00210 }
00211 else if ((strncmp(tempstr, "ALWAYS_VALIDATE", 15) == 0)
00212 && tokenlength == 15) {
00213 _dods_always_validate = atoi(value);
00214 }
00215 else if ((strncmp(tempstr, "VALIDATE_SSL", 12) == 0)
00216 && tokenlength == 12) {
00217 d_validate_ssl = atoi(value);
00218 }
00219 else if (strncmp(tempstr, "AIS_DATABASE", 12) == 0
00220 && tokenlength == 12) {
00221 d_ais_database = value;
00222 }
00223 else if (strncmp(tempstr, "COOKIE_JAR", 10) == 0
00224 && tokenlength == 10) {
00225
00226
00227
00228 if (value[0] == '/') {
00229 d_cookie_jar = value;
00230 }
00231 else {
00232 d_cookie_jar = d_rc_file_path.substr(0, d_rc_file_path.find(".dodsrc")) + string(value);
00233 }
00234 DBG(cerr << "set cookie jar to: " << d_cookie_jar << endl);
00235 }
00236 else if ((strncmp(tempstr, "PROXY_SERVER", 12) == 0)
00237 && tokenlength == 12) {
00238
00239
00240
00241
00242
00243
00244 string proxy = value;
00245 string::size_type comma = proxy.find(',');
00246
00247
00248
00249 if (comma != string::npos) {
00250 d_dods_proxy_server_protocol = proxy.substr(0, comma);
00251 downcase(d_dods_proxy_server_protocol);
00252 if (d_dods_proxy_server_protocol != "http")
00253 throw Error("The only supported protocol for a proxy server is \"HTTP\". Correct your \".dodsrc\" file.");
00254 proxy = proxy.substr(comma + 1);
00255 }
00256 else {
00257 d_dods_proxy_server_protocol = "http";
00258 }
00259
00260
00261 string::size_type protocol = proxy.find("://");
00262 if (protocol != string::npos) {
00263 proxy = proxy.substr(protocol + 3);
00264 }
00265
00266
00267 string::size_type at_sign = proxy.find('@');
00268 if (at_sign != string::npos) {
00269 d_dods_proxy_server_userpw = proxy.substr(0, at_sign);
00270 proxy = proxy.substr(at_sign + 1);
00271 }
00272 else
00273 d_dods_proxy_server_userpw = "";
00274
00275
00276 string::size_type colon = proxy.find(':');
00277 if (colon != string::npos) {
00278 d_dods_proxy_server_host = proxy.substr(0, colon);
00279 d_dods_proxy_server_port
00280 = strtol(proxy.substr(colon + 1).c_str(), 0, 0);
00281 }
00282 else {
00283 d_dods_proxy_server_host = proxy;
00284 d_dods_proxy_server_port = 80;
00285 }
00286 }
00287 else if ((strncmp(tempstr, "NO_PROXY_FOR", 12) == 0)
00288 && tokenlength == 12) {
00289
00290 string no_proxy = value;
00291 string::size_type comma = no_proxy.find(',');
00292
00293
00294
00295 if (comma == string::npos) {
00296 d_dods_no_proxy_for_protocol = "http";
00297 d_dods_no_proxy_for_host = no_proxy;
00298 d_dods_no_proxy_for = true;
00299 }
00300 else {
00301 d_dods_no_proxy_for_protocol = no_proxy.substr(0, comma);
00302 d_dods_no_proxy_for_host = no_proxy.substr(comma + 1);
00303 d_dods_no_proxy_for = true;
00304 }
00305 }
00306 }
00307
00308 delete [] tempstr; tempstr = 0;
00309
00310 fpi.close();
00311
00312 return true;
00313 }
00314
00315 return false;
00316 }
00317
00318
00319
00320
00321 string
00322 RCReader::check_string(string env_var)
00323 {
00324 DBG(cerr << "Entering check_string... (" << env_var << ")" << endl);
00325 struct stat stat_info;
00326
00327 if (stat(env_var.c_str(), &stat_info) != 0) {
00328 DBG(cerr << "stat returned non-zero" << endl);
00329 return "";
00330 }
00331
00332 if (S_ISREG(stat_info.st_mode)) {
00333 DBG(cerr << "S_ISREG: " << S_ISREG(stat_info.st_mode) << endl);
00334 return env_var;
00335 }
00336
00337
00338
00339 if (S_ISDIR(stat_info.st_mode)) {
00340 DBG(cerr << "S_ISDIR: " << S_ISDIR(stat_info.st_mode) << endl);
00341 if (*env_var.rbegin() != DIR_SEP_CHAR)
00342 env_var += DIR_SEP_STRING;
00343
00344
00345
00346
00347 d_cache_root = env_var + string(".dods_cache") + DIR_SEP_STRING;
00348 env_var += ".dodsrc";
00349 if (stat(env_var.c_str(), &stat_info) == 0 &&
00350 S_ISREG(stat_info.st_mode)) {
00351 DBG(cerr << "Found .dodsrc in \"" << env_var << "\"" << endl);
00352 return env_var;
00353 }
00354
00355
00356
00357
00358 if (write_rc_file(env_var)) {
00359 DBG(cerr << "Wrote .dodsrc in \"" << env_var << "\"" << endl);
00360 return env_var;
00361 }
00362 }
00363
00364
00365 DBG(cerr << "could neither find nor create a .dodsrc file" << endl);
00366 return "";
00367 }
00368
00378 string
00379 RCReader::check_env_var(const string &variable_name)
00380 {
00381 char *ev = getenv(variable_name.c_str());
00382 if (!ev || strlen(ev) == 0)
00383 return "";
00384
00385 return check_string(ev);
00386 }
00387
00388 RCReader::RCReader() throw(Error)
00389 {
00390 d_rc_file_path = "";
00391 d_cache_root = "";
00392
00393
00394
00395 _dods_use_cache = false;
00396 _dods_cache_max = 20;
00397 _dods_cached_obj = 5;
00398 _dods_ign_expires = 0;
00399 _dods_default_expires = 86400;
00400 _dods_always_validate = 0;
00401
00402 _dods_deflate = 0;
00403 d_validate_ssl = 1;
00404
00405
00406
00407 d_dods_proxy_server_protocol = "";
00408 d_dods_proxy_server_host = "";
00409 d_dods_proxy_server_port = 0;
00410 d_dods_proxy_server_userpw = "";
00411
00412 _dods_proxy_server_host_url = "";
00413
00414
00415
00416 _dods_proxy_for = false;
00417 _dods_proxy_for_regexp = "";
00418 _dods_proxy_for_proxy_host_url = "";
00419 _dods_proxy_for_regexp_flags = 0;
00420
00421
00422
00423 d_dods_no_proxy_for = false;
00424 d_dods_no_proxy_for_protocol = "";
00425 d_dods_no_proxy_for_host = "";
00426
00427
00428
00429 _dods_no_proxy_for_port = 0;
00430
00431 d_cookie_jar = "";
00432
00433 #ifdef WIN32
00434 string homedir = string("C:") + string(DIR_SEP_STRING) + string("Dods");
00435 d_rc_file_path = check_string(homedir);
00436 if (d_rc_file_path.empty()) {
00437 homedir = string("C:") + string(DIR_SEP_STRING) + string("opendap");
00438 d_rc_file_path = check_string(homedir);
00439 }
00440
00441 if (d_rc_file_path.empty())
00442 d_rc_file_path = check_env_var("APPDATA");
00443 if (d_rc_file_path.empty())
00444 d_rc_file_path = check_env_var("TEMP");
00445 if (d_rc_file_path.empty())
00446 d_rc_file_path = check_env_var("TMP");
00447 #else
00448 d_rc_file_path = check_env_var("DODS_CONF");
00449 if (d_rc_file_path.empty())
00450 d_rc_file_path = check_env_var("HOME");
00451 #endif
00452 DBG(cerr << "Looking for .dodsrc in: " << d_rc_file_path << endl);
00453
00454 if (!d_rc_file_path.empty())
00455 read_rc_file(d_rc_file_path);
00456 }
00457
00458 RCReader::~RCReader()
00459 {}
00460
00462 void
00463 RCReader::delete_instance()
00464 {
00465 if (RCReader::_instance) {
00466 delete RCReader::_instance;
00467 RCReader::_instance = 0;
00468 }
00469 }
00470
00472 void
00473 RCReader::initialize_instance()
00474 {
00475 DBGN(cerr << "RCReader::initialize_instance() ... ");
00476
00477 RCReader::_instance = new RCReader;
00478 atexit(RCReader::delete_instance);
00479
00480 DBG(cerr << "exiting." << endl);
00481 }
00482
00483 RCReader*
00484 RCReader::instance()
00485 {
00486 DBG(cerr << "Entring RCReader::instance" << endl);
00487
00488
00489 pthread_once(&instance_control, initialize_instance);
00490
00491 DBG(cerr << "Instance value: " << hex << _instance << dec << endl);
00492
00493 return _instance;
00494 }
00495
00496 }