// ConnectionResolver.cxx #include "dataset_catalog/ConnectionResolver.h" #include #include #include "dataset_util/Environment.h" #include "dataset_util/Text.h" #include "dataset_util/pthread_sleep.h" #include "dataset_util/SystemCommand.h" using std::string; using std::cerr; using std::endl; using dset::ConnectionResolver; //********************************************************************** // Local Definitions. //********************************************************************** namespace { //********************************************************************** // Name for the configuration file. string& config_file() { static string cfile = Environment::initial().value("DIAL_CATALOG_CONF"); return cfile; } Text config_text() { string prefix = "ConnectionResolver::config_text: "; string cfile = config_file(); if ( cfile.substr(0,7) == "http://" ) { SystemCommand scom("wget " + cfile + " -O - --cache=off"); if ( ! scom.was_run() ) { int maxtry = 10; for ( int itry=0; itry<10; ++itry ) { scom.runerr(); if ( scom.out().size() ) break; cerr << prefix << "Unable to resolve DIAL_CATALOG_CONF" << endl; cerr << scom << endl; cerr << "Try " << itry+1 << " of " << maxtry << endl << endl; pthread_sleep(itry); } } return scom.out(); } return Text(cfile); } //********************************************************************** // Resolve the password. // If the string "" is present in the file instead of the // password, retrieve password from "$HOME/.dial/pwNAME" where "NAME" // is the name of the database. // Returns the modified line for success. // Returns "" for failure; string resolve_passwd(string& line) { string prefix = "ConnectionResolver::resolve_passwd: "; string::size_type ipwpos = line.rfind(":"); // If ":" is not found, return the line if ( ipwpos == string::npos ) return ""; // Else replace "" with correct password, if present. string pass = line.substr(ipwpos+1); if ( pass == "" ) { string::size_type idbpos = line.find(":"); string::size_type jdbpos = line.find(":", idbpos+1); string dbname = line.substr(idbpos+1, jdbpos-(idbpos+1)); string home = Environment::initial().value("HOME"); string pwfile = home + "/.dial/pw" + line.substr(0,ipwpos); Text pwtxt(pwfile); if ( pwtxt.size() == 1 ) { string passwd = pwtxt.line(0); string startlineline = line.substr(0, ipwpos+1); line = startlineline + passwd; } else { cerr << prefix << "Unable to find password in file:" << endl; cerr << " " << pwfile << endl; return ""; } } return line; } } // end unnamed namespace //********************************************************************** // Static methods. //********************************************************************** // Set the name for the configuration file. // Default is $DIAL_CATALOG_CONF. void ConnectionResolver::set_configuration_file(string cfile) { config_file() = cfile; } //********************************************************************** // Return the name for the configuration file. string ConnectionResolver::get_configuration_file() { return config_file(); } //********************************************************************** // Return the name from a location in a connection string. string ConnectionResolver::location_name(std::string conn) { Text::WordList fields = Text::split(conn, ":@ "); if ( fields.size() == 0 ) return ""; return fields.front(); } //********************************************************************** // Return the name for the configuration file. string ConnectionResolver::accessor_name(std::string conn) { Text::WordList accs = Text::split(conn, "@", false); if ( accs.size() <= 1 ) return ""; string acc = accs.back(); return location_name(acc); } //********************************************************************** // Member functions //********************************************************************** // Default constructor. ConnectionResolver::ConnectionResolver() : m_txt(config_text()) { } //********************************************************************** // Destructor. ConnectionResolver::~ConnectionResolver() { } //********************************************************************** // Validity. bool ConnectionResolver::is_valid() const { return m_txt.size(); } //********************************************************************** // Return the string with the longest match. // **** This should be the *first* match **** // Which is it? string ConnectionResolver:: resolve(string type, string conn, bool findpass) const { // Find the line with catalog type. unsigned int lno = 0; string line, tag; while ( lno < m_txt.size() ) { line = m_txt.line(lno); // Ignore comments and blank lines // Check if the line matches the catalog name if ( ( line.size() || line[0] != '#' ) && line == type ) { ++lno; break; } ++lno; } // Return "" if catalog type is not found. if ( lno == m_txt.size() ) return ""; // If catalog name is found, check if the connection string is // the prefix of any string under the catalog. Return the // first string with which it matches. // ** This should be changed to match using words *** line = m_txt.line(lno); while ( line.size() && lno < m_txt.size() ) { // If the connection string is empty, take the first line. // resolve passwd // for the first line and return it if ( conn.empty() ) { if ( findpass ) resolve_passwd(line); return line; } // Otherwise, consider a match only if it is a prefix if ( line.find(conn) == 0 ) { // Check if technology specified is valid string ltech = line; string ptech = conn; string::size_type lpos = line.find(":"); string::size_type ppos = conn.find(":"); if ( lpos != string::npos ) ltech = line.substr(0, lpos); if ( ppos != string::npos ) ptech = line.substr(0, ppos); // Resolve passwd only if technology is valid if ( ltech != ptech ) break; if ( findpass ) resolve_passwd(line); return line; } ++lno; line = m_txt.line(lno); } return ""; } //**********************************************************************