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 fpo.close();
00135
00136 return true;
00137 }
00138
00139 return false;
00140 }
00141
00142 bool
00143 RCReader::read_rc_file(const string &pathname)
00144 {
00145 DBG(cerr << "Reading the RC file from " << pathname << endl);
00146
00147 ifstream fpi(pathname.c_str());
00148 if (fpi) {
00149
00150
00151
00152
00153 char *value;
00154 char *tempstr = new char[1024];;
00155 int tokenlength;
00156 while (true) {
00157 fpi.getline(tempstr, 1023);
00158 if (!fpi.good())
00159 break;
00160
00161 value = strchr(tempstr, '=');
00162 if (!value)
00163 continue;
00164 tokenlength = value - tempstr;
00165 value++;
00166
00167 if ((strncmp(tempstr, "USE_CACHE", 9) == 0)
00168 && tokenlength == 9) {
00169 _dods_use_cache = atoi(value) ? true : false;
00170 }
00171 else if ((strncmp(tempstr, "MAX_CACHE_SIZE", 14) == 0)
00172 && tokenlength == 14) {
00173 _dods_cache_max = atoi(value);
00174 }
00175 else if ((strncmp(tempstr, "MAX_CACHED_OBJ", 14) == 0)
00176 && tokenlength == 14) {
00177 _dods_cached_obj = atoi(value);
00178 }
00179 else if ((strncmp(tempstr, "IGNORE_EXPIRES", 14) == 0)
00180 && tokenlength == 14) {
00181 _dods_ign_expires = atoi(value);
00182 }
00183 else if ((strncmp(tempstr, "DEFLATE", 7) == 0)
00184 && tokenlength == 7) {
00185 _dods_deflate = atoi(value) ? true : false;
00186 }
00187 else if ((strncmp(tempstr, "CACHE_ROOT", 10) == 0)
00188 && tokenlength == 10) {
00189 d_cache_root = value;
00190 if (d_cache_root[d_cache_root.length() - 1] != DIR_SEP_CHAR)
00191 d_cache_root += string(DIR_SEP_STRING);
00192 }
00193 else if ((strncmp(tempstr, "DEFAULT_EXPIRES", 15) == 0)
00194 && tokenlength == 15) {
00195 _dods_default_expires = atoi(value);
00196 }
00197 else if ((strncmp(tempstr, "ALWAYS_VALIDATE", 15) == 0)
00198 && tokenlength == 15) {
00199 _dods_always_validate = atoi(value);
00200 }
00201 else if ((strncmp(tempstr, "VALIDATE_SSL", 12) == 0)
00202 && tokenlength == 12) {
00203 d_validate_ssl = atoi(value);
00204 }
00205 else if (strncmp(tempstr, "AIS_DATABASE", 12) == 0
00206 && tokenlength == 12) {
00207 d_ais_database = value;
00208 }
00209 else if ((strncmp(tempstr, "PROXY_SERVER", 12) == 0)
00210 && tokenlength == 12) {
00211
00212
00213
00214
00215
00216
00217 string proxy = value;
00218 string::size_type comma = proxy.find(',');
00219
00220
00221
00222 if (comma != string::npos) {
00223 d_dods_proxy_server_protocol = proxy.substr(0, comma);
00224 downcase(d_dods_proxy_server_protocol);
00225 if (d_dods_proxy_server_protocol != "http")
00226 throw Error("The only supported protocol for a proxy server is \"HTTP\". Correct your \".dodsrc\" file.");
00227 proxy = proxy.substr(comma + 1);
00228 }
00229 else {
00230 d_dods_proxy_server_protocol = "http";
00231 }
00232
00233
00234 string::size_type protocol = proxy.find("://");
00235 if (protocol != string::npos) {
00236 proxy = proxy.substr(protocol + 3);
00237 }
00238
00239
00240 string::size_type at_sign = proxy.find('@');
00241 if (at_sign != string::npos) {
00242 d_dods_proxy_server_userpw = proxy.substr(0, at_sign);
00243 proxy = proxy.substr(at_sign + 1);
00244 }
00245 else
00246 d_dods_proxy_server_userpw = "";
00247
00248
00249 string::size_type colon = proxy.find(':');
00250 if (colon != string::npos) {
00251 d_dods_proxy_server_host = proxy.substr(0, colon);
00252 d_dods_proxy_server_port
00253 = strtol(proxy.substr(colon + 1).c_str(), 0, 0);
00254 }
00255 else {
00256 d_dods_proxy_server_host = proxy;
00257 d_dods_proxy_server_port = 80;
00258 }
00259 }
00260 else if ((strncmp(tempstr, "NO_PROXY_FOR", 12) == 0)
00261 && tokenlength == 12) {
00262
00263 string no_proxy = value;
00264 string::size_type comma = no_proxy.find(',');
00265
00266
00267
00268 if (comma == string::npos) {
00269 d_dods_no_proxy_for_protocol = "http";
00270 d_dods_no_proxy_for_host = no_proxy;
00271 d_dods_no_proxy_for = true;
00272 }
00273 else {
00274 d_dods_no_proxy_for_protocol = no_proxy.substr(0, comma);
00275 d_dods_no_proxy_for_host = no_proxy.substr(comma + 1);
00276 d_dods_no_proxy_for = true;
00277 }
00278 }
00279 }
00280
00281 delete [] tempstr; tempstr = 0;
00282
00283 fpi.close();
00284
00285 return true;
00286 }
00287
00288 return false;
00289 }
00290
00291
00292
00293
00294 string
00295 RCReader::check_string(string env_var)
00296 {
00297 DBG(cerr << "Entering check_string... (" << env_var << ")" << endl);
00298 struct stat stat_info;
00299
00300 if (stat(env_var.c_str(), &stat_info) != 0) {
00301 DBG(cerr << "stat returned non-zero" << endl);
00302 return "";
00303 }
00304
00305 if (S_ISREG(stat_info.st_mode)) {
00306 DBG(cerr << "S_ISREG: " << S_ISREG(stat_info.st_mode) << endl);
00307 return env_var;
00308 }
00309
00310
00311
00312 if (S_ISDIR(stat_info.st_mode)) {
00313 DBG(cerr << "S_ISDIR: " << S_ISDIR(stat_info.st_mode) << endl);
00314 if (*env_var.rbegin() != DIR_SEP_CHAR)
00315 env_var += DIR_SEP_STRING;
00316
00317
00318
00319
00320 d_cache_root = env_var + string(".dods_cache") + DIR_SEP_STRING;
00321 env_var += ".dodsrc";
00322 if (stat(env_var.c_str(), &stat_info) == 0 &&
00323 S_ISREG(stat_info.st_mode)) {
00324 DBG(cerr << "Found .dodsrc in \"" << env_var << "\"" << endl);
00325 return env_var;
00326 }
00327
00328
00329
00330
00331 if (write_rc_file(env_var)) {
00332 DBG(cerr << "Wrote .dodsrc in \"" << env_var << "\"" << endl);
00333 return env_var;
00334 }
00335 }
00336
00337
00338 DBG(cerr << "could neither find nor create a .dodsrc file" << endl);
00339 return "";
00340 }
00341
00351 string
00352 RCReader::check_env_var(const string &variable_name)
00353 {
00354 char *ev = getenv(variable_name.c_str());
00355 if (!ev || strlen(ev) == 0)
00356 return "";
00357
00358 return check_string(ev);
00359 }
00360
00361 RCReader::RCReader() throw(Error)
00362 {
00363 d_rc_file_path = "";
00364 d_cache_root = "";
00365
00366
00367
00368 _dods_use_cache = false;
00369 _dods_cache_max = 20;
00370 _dods_cached_obj = 5;
00371 _dods_ign_expires = 0;
00372 _dods_default_expires = 86400;
00373 _dods_always_validate = 0;
00374
00375 _dods_deflate = 0;
00376 d_validate_ssl = 1;
00377
00378
00379
00380 d_dods_proxy_server_protocol = "";
00381 d_dods_proxy_server_host = "";
00382 d_dods_proxy_server_port = 0;
00383 d_dods_proxy_server_userpw = "";
00384
00385 _dods_proxy_server_host_url = "";
00386
00387
00388
00389 _dods_proxy_for = false;
00390 _dods_proxy_for_regexp = "";
00391 _dods_proxy_for_proxy_host_url = "";
00392 _dods_proxy_for_regexp_flags = 0;
00393
00394
00395
00396 d_dods_no_proxy_for = false;
00397 d_dods_no_proxy_for_protocol = "";
00398 d_dods_no_proxy_for_host = "";
00399
00400
00401
00402 _dods_no_proxy_for_port = 0;
00403
00404 #ifdef WIN32
00405 string homedir = string("C:") + string(DIR_SEP_STRING) + string("Dods");
00406 d_rc_file_path = check_string(homedir);
00407
00408 if (d_rc_file_path.empty())
00409 d_rc_file_path = check_env_var("APPDATA");
00410 if (d_rc_file_path.empty())
00411 d_rc_file_path = check_env_var("TEMP");
00412 if (d_rc_file_path.empty())
00413 d_rc_file_path = check_env_var("TMP");
00414 #else
00415 d_rc_file_path = check_env_var("DODS_CONF");
00416 if (d_rc_file_path.empty())
00417 d_rc_file_path = check_env_var("HOME");
00418 #endif
00419 DBG(cerr << "Looking for .dodsrc in: " << d_rc_file_path << endl);
00420
00421 if (!d_rc_file_path.empty())
00422 read_rc_file(d_rc_file_path);
00423 }
00424
00425 RCReader::~RCReader()
00426 {}
00427
00429 void
00430 RCReader::delete_instance()
00431 {
00432 if (RCReader::_instance) {
00433 delete RCReader::_instance;
00434 RCReader::_instance = 0;
00435 }
00436 }
00437
00439 void
00440 RCReader::initialize_instance()
00441 {
00442 DBGN(cerr << "RCReader::initialize_instance() ... ");
00443
00444 RCReader::_instance = new RCReader;
00445 atexit(RCReader::delete_instance);
00446
00447 DBG(cerr << "exiting." << endl);
00448 }
00449
00450 RCReader*
00451 RCReader::instance()
00452 {
00453 DBG(cerr << "Entring RCReader::instance" << endl);
00454
00455
00456 pthread_once(&instance_control, initialize_instance);
00457
00458 DBG(cerr << "Instance value: " << hex << _instance << dec << endl);
00459 return _instance;
00460 }
00461
00462 }