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