configfile.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "configfile.h"
00023 #include "error.h"
00024 #include "r_message.h"
00025 #include <pwd.h>
00026 #include <string.h>
00027 #include <errno.h>
00028 #include <unistd.h>
00029 #include <fstream>
00030 #include <sstream>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033
00034 namespace Barry {
00035
00036 bool ConfigFile::DBListType::IsSelected(const std::string &dbname) const
00037 {
00038 const_iterator i = begin();
00039 for( ; i != end(); ++i ) {
00040 if( *i == dbname ) {
00041 return true;
00042 }
00043 }
00044 return false;
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 ConfigFile::ConfigFile(Barry::Pin pin)
00057 : m_pin(pin)
00058 , m_loaded(false)
00059 , m_promptBackupLabel(false)
00060 {
00061 if( m_pin == 0 )
00062 throw ConfigFileError("Configfile: empty pin");
00063
00064 BuildFilename();
00065 BuildDefaultPath();
00066 Load();
00067 }
00068
00069
00070
00071
00072 ConfigFile::ConfigFile(Barry::Pin pin,
00073 const Barry::DatabaseDatabase &db)
00074 : m_pin(pin)
00075 , m_loaded(false)
00076 , m_promptBackupLabel(false)
00077 {
00078 if( m_pin == 0 )
00079 throw ConfigFileError("Configfile: empty pin");
00080
00081 BuildFilename();
00082 BuildDefaultPath();
00083 Load();
00084 Enlighten(db);
00085 }
00086
00087 ConfigFile::~ConfigFile()
00088 {
00089 }
00090
00091 void ConfigFile::BuildFilename()
00092 {
00093 size_t strsize = 255 * 5;
00094 char *strbuf = new char[strsize];
00095 struct passwd pwbuf;
00096 struct passwd *pw;
00097
00098 getpwuid_r(getuid(), &pwbuf, strbuf, strsize, &pw);
00099 if( !pw ) {
00100 delete [] strbuf;
00101 throw ConfigFileError("BuildFilename: getpwuid failed", errno);
00102 }
00103
00104 m_filename = pw->pw_dir;
00105 m_filename += "/.barry/backup/";
00106 m_filename += m_pin.Str();
00107 m_filename += "/config";
00108
00109 delete [] strbuf;
00110 }
00111
00112 void ConfigFile::BuildDefaultPath()
00113 {
00114 struct passwd *pw = getpwuid(getuid());
00115 m_path = pw->pw_dir;
00116 m_path += "/.barry/backup/";
00117 m_path += m_pin.Str();
00118 }
00119
00120 void ConfigFile::Clear()
00121 {
00122 m_loaded = false;
00123 m_backupList.clear();
00124 m_restoreList.clear();
00125 m_deviceName.clear();
00126 m_promptBackupLabel = false;
00127 }
00128
00129
00130 void ConfigFile::Load()
00131 {
00132
00133 Clear();
00134
00135
00136 std::ifstream in(m_filename.c_str(), std::ios::in | std::ios::binary);
00137 if( !in )
00138 return;
00139
00140 std::string line;
00141 DBListType *pList = 0;
00142
00143 while( std::getline(in, line) ) {
00144 std::string keyword;
00145 std::istringstream iss(line);
00146 iss >> keyword;
00147
00148 if( keyword == "backup_list" ) {
00149 pList = &m_backupList;
00150 }
00151 else if( keyword == "restore_list" ) {
00152 pList = &m_restoreList;
00153 }
00154 else if( line[0] == ' ' && pList ) {
00155 pList->push_back(line.c_str() + 1);
00156 }
00157 else {
00158 pList = 0;
00159
00160
00161 if( keyword == "device_name" ) {
00162 iss >> std::ws;
00163 std::getline(iss, m_deviceName);
00164 if( m_deviceName.size() == 0 ) {
00165
00166
00167
00168
00169
00170 m_deviceName = " ";
00171 }
00172 }
00173 else if( keyword == "backup_path" ) {
00174 iss >> std::ws;
00175 std::getline(iss, m_path);
00176 if( (m_path.size() == 0) || !(CheckPath(m_path)))
00177 BuildDefaultPath();
00178 }
00179 else if( keyword == "prompt_backup_label" ) {
00180 int flag;
00181 iss >> flag;
00182 m_promptBackupLabel = flag;
00183 }
00184 }
00185 }
00186
00187 m_loaded = true;
00188 }
00189
00190
00191 bool ConfigFile::Save()
00192 {
00193 if( !CheckPath(m_path, &m_last_error) )
00194 return false;
00195
00196 std::ofstream out(m_filename.c_str(), std::ios::out | std::ios::binary);
00197 if( !out ) {
00198 m_last_error = "Unable to open " + m_filename + " for writing.";
00199 return false;
00200 }
00201
00202 out << "backup_list" << std::endl;
00203 for( DBListType::iterator i = m_backupList.begin(); i != m_backupList.end(); ++i ) {
00204 out << " " << *i << std::endl;
00205 }
00206
00207 out << "restore_list" << std::endl;
00208 for( DBListType::iterator i = m_restoreList.begin(); i != m_restoreList.end(); ++i ) {
00209 out << " " << *i << std::endl;
00210 }
00211
00212 if( m_deviceName.size() ) {
00213 out << "device_name " << m_deviceName << std::endl;
00214 }
00215
00216 if( m_path.size() ) {
00217 out << "backup_path " << m_path << std::endl;
00218 }
00219
00220 out << "prompt_backup_label " << (m_promptBackupLabel ? 1 : 0) << std::endl;
00221
00222 if( !out ) {
00223 m_last_error = "Error during write. Config may be incomplete.";
00224 return false;
00225 }
00226 return true;
00227 }
00228
00229
00230
00231
00232 void ConfigFile::Enlighten(const Barry::DatabaseDatabase &db)
00233 {
00234 if( !m_loaded ) {
00235
00236
00237
00238
00239 m_backupList.clear();
00240 m_restoreList.clear();
00241
00242 Barry::DatabaseDatabase::DatabaseArrayType::const_iterator i =
00243 db.Databases.begin();
00244 for( ; i != db.Databases.end(); ++i ) {
00245
00246 m_backupList.push_back(i->Name);
00247
00248
00249
00250 if( i->Name != Barry::Message::GetDBName() &&
00251 i->Name != "Handheld Agent" )
00252 {
00253 m_restoreList.push_back(i->Name);
00254 }
00255 }
00256 }
00257 }
00258
00259
00260 void ConfigFile::SetBackupList(const DBListType &list)
00261 {
00262 m_backupList = list;
00263 m_loaded = true;
00264 }
00265
00266 void ConfigFile::SetRestoreList(const DBListType &list)
00267 {
00268 m_restoreList = list;
00269 m_loaded = true;
00270 }
00271
00272 void ConfigFile::SetDeviceName(const std::string &name)
00273 {
00274 if( name.size() )
00275 m_deviceName = name;
00276 else
00277 m_deviceName = " ";
00278 }
00279
00280 void ConfigFile::SetBackupPath(const std::string &path)
00281 {
00282 if( path.size() && CheckPath(path) )
00283 m_path = path;
00284 else
00285 BuildDefaultPath();
00286 }
00287
00288 void ConfigFile::SetPromptBackupLabel(bool prompt)
00289 {
00290 m_promptBackupLabel = prompt;
00291 }
00292
00293
00294
00295 bool ConfigFile::CheckPath(const std::string &path, std::string *perr)
00296 {
00297 if( path.size() == 0 ) {
00298 if( perr )
00299 *perr = "path is empty!";
00300 return false;
00301 }
00302
00303 if( access(path.c_str(), F_OK) == 0 )
00304 return true;
00305
00306 std::string base;
00307 std::string::size_type slash = 0;
00308 while( (slash = path.find('/', slash + 1)) != std::string::npos ) {
00309 base = path.substr(0, slash);
00310 if( access(base.c_str(), F_OK) != 0 ) {
00311 if( mkdir(base.c_str(), 0755) == -1 ) {
00312 if( perr ) {
00313 *perr = "mkdir(" + base + ") failed: ";
00314 *perr += strerror(errno);
00315 }
00316 return false;
00317 }
00318 }
00319 }
00320 if( mkdir(path.c_str(), 0755) == -1 ) {
00321 if( perr ) {
00322 *perr = "last mkdir(" + path + ") failed: ";
00323 *perr += strerror(errno);
00324 }
00325 return false;
00326 }
00327 return true;
00328 }
00329
00330
00331
00332
00333
00334
00335 GlobalConfigFile::GlobalConfigFile()
00336 : m_loaded(false)
00337 , m_verboseLogging(false)
00338 {
00339 BuildFilename();
00340 Load();
00341 }
00342
00343 GlobalConfigFile::GlobalConfigFile(const std::string &appname)
00344 : m_loaded(false)
00345 , m_appname(appname)
00346 , m_verboseLogging(false)
00347 {
00348
00349 if( m_appname.find(' ') != std::string::npos )
00350 throw std::logic_error("App name must have no spaces.");
00351
00352 BuildFilename();
00353 Load();
00354 }
00355
00356 GlobalConfigFile::~GlobalConfigFile()
00357 {
00358 }
00359
00360 void GlobalConfigFile::BuildFilename()
00361 {
00362 struct passwd *pw = getpwuid(getuid());
00363 if( !pw )
00364 throw ConfigFileError("BuildFilename: getpwuid failed", errno);
00365
00366 m_filename = pw->pw_dir;
00367 m_filename += "/.barry/config";
00368
00369
00370 m_path = pw->pw_dir;
00371 m_path += "/.barry";
00372 }
00373
00374 void GlobalConfigFile::Clear()
00375 {
00376 m_loaded = false;
00377 m_lastDevice = 0;
00378 }
00379
00380 void GlobalConfigFile::Load()
00381 {
00382
00383 Clear();
00384
00385
00386 std::ifstream in(m_filename.c_str(), std::ios::in | std::ios::binary);
00387 if( !in )
00388 return;
00389
00390 std::string line;
00391
00392 while( std::getline(in, line) ) {
00393 std::string keyword;
00394 std::istringstream iss(line);
00395 iss >> keyword;
00396
00397 if( keyword == "last_device" ) {
00398 iss >> std::ws;
00399 m_lastDevice.Clear();
00400 iss >> m_lastDevice;
00401 }
00402 else if( keyword == "verbose_logging" ) {
00403 int flag = 0;
00404 iss >> flag;
00405 m_verboseLogging = flag;
00406 }
00407 else {
00408
00409 if( keyword.substr(0, 2) == "X-" ) {
00410 iss >> std::ws;
00411 line.clear();
00412 std::getline(iss, line);
00413 m_keymap[keyword] = line;
00414 }
00415 }
00416 }
00417
00418 m_loaded = true;
00419 }
00420
00421
00422 bool GlobalConfigFile::Save()
00423 {
00424 if( !ConfigFile::CheckPath(m_path, &m_last_error) )
00425 return false;
00426
00427 std::ofstream out(m_filename.c_str(), std::ios::out | std::ios::binary);
00428 if( !out ) {
00429 m_last_error = "Unable to open " + m_filename + " for writing.";
00430 return false;
00431 }
00432
00433 if( !(m_lastDevice == 0) ) {
00434 out << "last_device " << m_lastDevice.Str() << std::endl;
00435 }
00436
00437 out << "verbose_logging " << (m_verboseLogging ? 1 : 0) << std::endl;
00438
00439
00440 keymap_type::const_iterator ci = m_keymap.begin();
00441 for( ; ci != m_keymap.end(); ++ci ) {
00442 out << ci->first << " " << ci->second << std::endl;
00443 }
00444
00445 if( !out ) {
00446 m_last_error = "Error during write. Config may be incomplete.";
00447 return false;
00448 }
00449 return true;
00450 }
00451
00452 void GlobalConfigFile::SetKey(const std::string &key, const std::string &value)
00453 {
00454 if( !m_appname.size() )
00455 throw std::logic_error("Cannot use SetKey() without specifying an appname in the constructor.");
00456
00457 if( value.find_first_of("\n\r") != std::string::npos )
00458 throw std::logic_error("SetKey values may not contain newline characters.");
00459
00460 std::string fullkey = "X-" + m_appname + "-" + key;
00461 m_keymap[fullkey] = value;
00462 }
00463
00464 std::string GlobalConfigFile::GetKey(const std::string &key) const
00465 {
00466 if( !m_appname.size() )
00467 throw std::logic_error("Cannot use SetKey() without specifying an appname in the constructor.");
00468
00469 std::string fullkey = "X-" + m_appname + "-" + key;
00470 keymap_type::const_iterator ci = m_keymap.find(fullkey);
00471 if( ci == m_keymap.end() )
00472 return "";
00473 return ci->second;
00474 }
00475
00476 void GlobalConfigFile::SetLastDevice(const Barry::Pin &pin)
00477 {
00478 m_lastDevice = pin;
00479 }
00480
00481 void GlobalConfigFile::SetVerboseLogging(bool verbose)
00482 {
00483 m_verboseLogging = verbose;
00484 }
00485
00486
00487 }
00488