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