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 #include "config.h"
00038
00039 #include <cstring>
00040
00041 #include <unistd.h>
00042 #include <sys/types.h>
00043 #include <sys/stat.h>
00044
00045 #ifdef WIN32
00046 #define FALSE 0
00047
00048 #define F_OK 0
00049 #define DIR_SEP_STRING "\\"
00050 #define DIR_SEP_CHAR '\\'
00051 #include <direct.h>
00052 #else
00053 #define DIR_SEP_STRING "/"
00054 #define DIR_SEP_CHAR '/'
00055 #endif
00056
00057 #include <pthread.h>
00058
00059 #include <fstream>
00060
00061 #include "debug.h"
00062 #include "RCReader.h"
00063 #include "Error.h"
00064
00065 using namespace std;
00066
00067 namespace libdap {
00068
00069 RCReader* RCReader::_instance = 0;
00070
00071
00072
00073
00074 static pthread_once_t instance_control = PTHREAD_ONCE_INIT;
00075
00080 bool
00081 RCReader::write_rc_file(const string &pathname)
00082 {
00083 DBG(cerr << "Writing the RC file to " << pathname << endl);
00084 ofstream fpo(pathname.c_str());
00085
00086
00087
00088
00089 if (fpo) {
00090
00091
00092 fpo << "# OPeNDAP client configuation file. See the OPeNDAP" << endl;
00093 fpo << "# users guide for information." << endl;
00094 fpo << "USE_CACHE=" << _dods_use_cache << endl;
00095 fpo << "# Cache and object size are given in megabytes (20 ==> 20Mb)."
00096 << endl;
00097 fpo << "MAX_CACHE_SIZE=" << _dods_cache_max << endl;
00098 fpo << "MAX_CACHED_OBJ=" << _dods_cached_obj << endl;
00099 fpo << "IGNORE_EXPIRES=" << _dods_ign_expires << endl;
00100 fpo << "CACHE_ROOT=" << d_cache_root << endl;
00101 fpo << "DEFAULT_EXPIRES=" << _dods_default_expires << endl;
00102 fpo << "ALWAYS_VALIDATE=" << _dods_always_validate << endl;
00103 fpo << "# Request servers compress responses if possible?" << endl;
00104 fpo << "# 1 (yes) or 0 (false)." << endl;
00105 fpo << "DEFLATE=" << _dods_deflate << endl;
00106
00107 fpo << "# Should SSL certificates and hosts be validated? SSL" << endl;
00108 fpo << "# will only work with signed certificates." << endl;
00109 fpo << "VALIDATE_SSL=" << d_validate_ssl << endl;
00110
00111 fpo << "# Proxy configuration:" << endl;
00112 fpo << "# PROXY_SERVER=<protocol>,<[username:password@]host[:port]>"
00113 << endl;
00114 if (!d_dods_proxy_server_host.empty()) {
00115 fpo << "PROXY_SERVER=" << d_dods_proxy_server_protocol << ","
00116 << (d_dods_proxy_server_userpw.empty()
00117 ? ""
00118 : d_dods_proxy_server_userpw + "@")
00119 + d_dods_proxy_server_host
00120 + ":" + long_to_string(d_dods_proxy_server_port) << endl;
00121 }
00122
00123 fpo << "# NO_PROXY_FOR=<protocol>,<host|domain>" << endl;
00124 if (!d_dods_no_proxy_for_host.empty()) {
00125 fpo << "NO_PROXY_FOR=" << d_dods_no_proxy_for_protocol << ","
00126 << d_dods_no_proxy_for_host << endl;
00127 }
00128
00129 fpo << "# AIS_DATABASE=<file or url>" << endl;
00130 fpo.close();
00131
00132 return true;
00133 }
00134
00135 return false;
00136 }
00137
00138 bool
00139 RCReader::read_rc_file(const string &pathname)
00140 {
00141 DBG(cerr << "Reading the RC file from " << pathname << endl);
00142
00143 ifstream fpi(pathname.c_str());
00144 if (fpi) {
00145
00146
00147
00148
00149 char *value;
00150 char *tempstr = new char[1024];;
00151 int tokenlength;
00152 while (true) {
00153 fpi.getline(tempstr, 1023);
00154 if (!fpi.good())
00155 break;
00156
00157 value = strchr(tempstr, '=');
00158 if (!value)
00159 continue;
00160 tokenlength = value - tempstr;
00161 value++;
00162
00163 if ((strncmp(tempstr, "USE_CACHE", 9) == 0)
00164 && tokenlength == 9) {
00165 _dods_use_cache = atoi(value) ? true : false;
00166 }
00167 else if ((strncmp(tempstr, "MAX_CACHE_SIZE", 14) == 0)
00168 && tokenlength == 14) {
00169 _dods_cache_max = atoi(value);
00170 }
00171 else if ((strncmp(tempstr, "MAX_CACHED_OBJ", 14) == 0)
00172 && tokenlength == 14) {
00173 _dods_cached_obj = atoi(value);
00174 }
00175 else if ((strncmp(tempstr, "IGNORE_EXPIRES", 14) == 0)
00176 && tokenlength == 14) {
00177 _dods_ign_expires = atoi(value);
00178 }
00179 else if ((strncmp(tempstr, "DEFLATE", 7) == 0)
00180 && tokenlength == 7) {
00181 _dods_deflate = atoi(value) ? true : false;
00182 }
00183 else if ((strncmp(tempstr, "CACHE_ROOT", 10) == 0)
00184 && tokenlength == 10) {
00185 d_cache_root = value;
00186 if (d_cache_root[d_cache_root.length() - 1] != DIR_SEP_CHAR)
00187 d_cache_root += string(DIR_SEP_STRING);
00188 }
00189 else if ((strncmp(tempstr, "DEFAULT_EXPIRES", 15) == 0)
00190 && tokenlength == 15) {
00191 _dods_default_expires = atoi(value);
00192 }
00193 else if ((strncmp(tempstr, "ALWAYS_VALIDATE", 15) == 0)
00194 && tokenlength == 15) {
00195 _dods_always_validate = atoi(value);
00196 }
00197 else if ((strncmp(tempstr, "VALIDATE_SSL", 12) == 0)
00198 && tokenlength == 12) {
00199 d_validate_ssl = atoi(value);
00200 }
00201 else if (strncmp(tempstr, "AIS_DATABASE", 12) == 0
00202 && tokenlength == 12) {
00203 d_ais_database = value;
00204 }
00205 else if ((strncmp(tempstr, "PROXY_SERVER", 12) == 0)
00206 && tokenlength == 12) {
00207
00208 string proxy = value;
00209 string::size_type comma = proxy.find(',');
00210
00211
00212
00213 if (comma == string::npos)
00214 continue;
00215 d_dods_proxy_server_protocol = proxy.substr(0, comma);
00216 proxy = proxy.substr(comma + 1);
00217
00218
00219 string::size_type at_sign = proxy.find('@');
00220 if (at_sign != string::npos) {
00221 d_dods_proxy_server_userpw = proxy.substr(0, at_sign);
00222 proxy = proxy.substr(at_sign + 1);
00223 }
00224 else
00225 d_dods_proxy_server_userpw = "";
00226
00227
00228 string::size_type colon = proxy.find(':');
00229 if (colon != string::npos) {
00230 d_dods_proxy_server_host = proxy.substr(0, colon);
00231 d_dods_proxy_server_port
00232 = strtol(proxy.substr(colon + 1).c_str(), 0, 0);
00233 }
00234 else {
00235 d_dods_proxy_server_host = proxy;
00236
00237 if (d_dods_proxy_server_protocol == "http")
00238 d_dods_proxy_server_port = 80;
00239 else if (d_dods_proxy_server_protocol == "https")
00240 d_dods_proxy_server_port = 443;
00241 else if (d_dods_proxy_server_protocol == "ftp")
00242 d_dods_proxy_server_port = 21;
00243 else throw Error("Could not determine the port to use for proxy '"
00244 + d_dods_proxy_server_host
00245 + ".' Please check your .dodsrc file.");
00246 }
00247 }
00248 else if ((strncmp(tempstr, "NO_PROXY_FOR", 12) == 0)
00249 && tokenlength == 12) {
00250
00251 string no_proxy = value;
00252 string::size_type comma = no_proxy.find(',');
00253
00254
00255
00256 if (comma == string::npos)
00257 continue;
00258 d_dods_no_proxy_for_protocol = no_proxy.substr(0, comma);
00259 d_dods_no_proxy_for_host = no_proxy.substr(comma + 1);
00260 d_dods_no_proxy_for = true;
00261 }
00262 }
00263
00264 delete [] tempstr; tempstr = 0;
00265
00266 fpi.close();
00267
00268 return true;
00269 }
00270
00271 return false;
00272 }
00273
00274
00275
00276
00277 string
00278 RCReader::check_string(string env_var)
00279 {
00280 struct stat stat_info;
00281
00282 if (stat(env_var.c_str(), &stat_info) != 0)
00283 return "";
00284
00285 if (S_ISREG(stat_info.st_mode))
00286 return env_var;
00287
00288
00289
00290 if (S_ISDIR(stat_info.st_mode)) {
00291 if (*env_var.rbegin() != DIR_SEP_CHAR)
00292 env_var += DIR_SEP_STRING;
00293
00294
00295
00296
00297 d_cache_root = env_var + string(".dods_cache") + DIR_SEP_STRING;
00298 env_var += ".dodsrc";
00299 if (stat(env_var.c_str(), &stat_info) == 0 &&
00300 S_ISREG(stat_info.st_mode))
00301 return env_var;
00302
00303
00304
00305
00306 if (write_rc_file(env_var))
00307 return env_var;
00308 }
00309
00310
00311 return "";
00312 }
00313
00323 string
00324 RCReader::check_env_var(const string &variable_name)
00325 {
00326 char *ev = getenv(variable_name.c_str());
00327 if (!ev || strlen(ev) == 0)
00328 return "";
00329
00330 return check_string(ev);
00331 }
00332
00333 RCReader::RCReader() throw(Error)
00334 {
00335 d_rc_file_path = "";
00336 d_cache_root = "";
00337
00338
00339
00340 _dods_use_cache = false;
00341 _dods_cache_max = 20;
00342 _dods_cached_obj = 5;
00343 _dods_ign_expires = 0;
00344 _dods_default_expires = 86400;
00345 _dods_always_validate = 0;
00346
00347 _dods_deflate = 0;
00348 d_validate_ssl = 1;
00349
00350
00351 d_dods_proxy_server_protocol = "";
00352 d_dods_proxy_server_host = "";
00353 d_dods_proxy_server_port = 0;
00354 d_dods_proxy_server_userpw = "";
00355
00356 _dods_proxy_server_host_url = "";
00357
00358
00359 _dods_proxy_for = false;
00360 _dods_proxy_for_regexp = "";
00361 _dods_proxy_for_proxy_host_url = "";
00362 _dods_proxy_for_regexp_flags = 0;
00363
00364
00365 d_dods_no_proxy_for = false;
00366 d_dods_no_proxy_for_protocol = "";
00367 d_dods_no_proxy_for_host = "";
00368
00369
00370
00371 _dods_no_proxy_for_port = 0;
00372
00373 #ifdef WIN32
00374 string homedir = string("C:") + string(DIR_SEP_STRING) + string("Dods");
00375 d_rc_file_path = check_string(homedir);
00376
00377 if (d_rc_file_path.empty())
00378 d_rc_file_path = check_env_var("APPDATA");
00379 if (d_rc_file_path.empty())
00380 d_rc_file_path = check_env_var("TEMP");
00381 if (d_rc_file_path.empty())
00382 d_rc_file_path = check_env_var("TMP");
00383 #else
00384 d_rc_file_path = check_env_var("DODS_CONF");
00385 if (d_rc_file_path.empty())
00386 d_rc_file_path = check_env_var("HOME");
00387 #endif
00388
00389 if (!d_rc_file_path.empty())
00390 read_rc_file(d_rc_file_path);
00391 }
00392
00393 RCReader::~RCReader()
00394 {}
00395
00397 void
00398 RCReader::delete_instance()
00399 {
00400 if (RCReader::_instance) {
00401 delete RCReader::_instance;
00402 RCReader::_instance = 0;
00403 }
00404 }
00405
00407 void
00408 RCReader::initialize_instance()
00409 {
00410 DBG(cerr << "RCReader::initialize_instance() ... ");
00411
00412 RCReader::_instance = new RCReader;
00413 atexit(RCReader::delete_instance);
00414
00415 DBGN(cerr << "exiting." << endl);
00416 }
00417
00418 RCReader*
00419 RCReader::instance()
00420 {
00421
00422
00423 pthread_once(&instance_control, initialize_instance);
00424
00425 return _instance;
00426 }
00427
00428 }