2 /// \file configfile.cc
3 /// Barry configuraion class, for one device PIN
7 Copyright (C) 2007-2013, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
23 #include "configfile.h"
25 #include "r_message.h"
32 #include <sys/types.h>
37 bool ConfigFile::DBListType::IsSelected(const std::string
&dbname
) const
39 const_iterator i
= begin();
40 for( ; i
!= end(); ++i
) {
48 std::ostream
& operator<< (std::ostream
&os
, const ConfigFile::DBListType
&list
)
50 os
<< _("DBListType dump:\n");
52 for( ConfigFile::DBListType::const_iterator i
= list
.begin();
56 os
<< " " << *i
<< "\n";
62 //////////////////////////////////////////////////////////////////////////////
63 // ConfigFile class members
65 /// Loads config file for the given pin, and ends up in an
66 /// unenlightened state. Throws ConfigFileError on error,
67 /// but it is not an error if the config does not exist.
68 /// Never use this if you have a DatabaseDatabase object!
69 /// This ctor is only for temporary loading of config data.
70 ConfigFile::ConfigFile(Barry::Pin pin
)
73 , m_promptBackupLabel(false)
74 , m_autoSelectAll(false)
77 throw ConfigFileError(_("Configfile: empty pin"));
80 BuildDefaultPath(); // this handles the situation that path is not set
84 /// Opens and loads config file for given pin, and calls Enlighten
85 /// Throws ConfigFileError on error. Should never fail unless
87 ConfigFile::ConfigFile(Barry::Pin pin
,
88 const Barry::DatabaseDatabase
&db
)
91 , m_promptBackupLabel(false)
92 , m_autoSelectAll(false)
95 throw ConfigFileError(_("Configfile: empty pin"));
103 ConfigFile::~ConfigFile()
107 void ConfigFile::Clear()
110 m_backupList
.clear();
111 m_restoreList
.clear();
112 m_deviceName
.clear();
113 m_promptBackupLabel
= false;
114 m_autoSelectAll
= false;
117 /// Attempt to load the configuration file, but do not fail if not available
118 void ConfigFile::Load()
124 std::ifstream
in(m_filename
.c_str(), std::ios::in
| std::ios::binary
);
129 DBListType
*pList
= 0;
131 while( std::getline(in
, line
) ) {
133 std::istringstream
iss(line
);
136 if( keyword
== "backup_list" ) {
137 pList
= &m_backupList
;
139 else if( keyword
== "restore_list" ) {
140 pList
= &m_restoreList
;
142 else if( line
[0] == ' ' && pList
) {
143 pList
->push_back(line
.c_str() + 1);
148 // add all remaining keyword checks here
149 if( keyword
== "device_name" ) {
151 std::getline(iss
, m_deviceName
);
152 if( m_deviceName
.size() == 0 ) {
153 // if there is a device_name setting,
154 // then this value must hold something,
155 // so that the user can ignore this
156 // field, and not get pestered all
161 else if( keyword
== "backup_path" ) {
163 std::getline(iss
, m_path
);
164 if( (m_path
.size() == 0) || !(CheckPath(m_path
)))
167 else if( keyword
== "prompt_backup_label" ) {
170 m_promptBackupLabel
= flag
!= 0;
172 else if( keyword
== "auto_select_all" ) {
175 m_autoSelectAll
= flag
!= 0;
183 /// Saves current device's config, overwriting or creating a config file
184 bool ConfigFile::Save()
188 if( !CheckPath(m_path
, &m_last_error
) )
191 ofstream
out(m_filename
.c_str(), std::ios::out
| std::ios::binary
);
193 m_last_error
= _("Unable to open file for writing: ") + m_filename
;
197 out
<< "backup_list" << endl
;
198 for( DBListType::iterator i
= m_backupList
.begin(); i
!= m_backupList
.end(); ++i
) {
199 out
<< " " << *i
<< endl
;
202 out
<< "restore_list" << endl
;
203 for( DBListType::iterator i
= m_restoreList
.begin(); i
!= m_restoreList
.end(); ++i
) {
204 out
<< " " << *i
<< endl
;
207 if( m_deviceName
.size() ) {
208 out
<< "device_name " << m_deviceName
<< endl
;
211 if( m_path
.size() ) {
212 out
<< "backup_path " << m_path
<< endl
;
215 out
<< "prompt_backup_label " << (m_promptBackupLabel
? 1 : 0) << endl
;
216 out
<< "auto_select_all " << (m_autoSelectAll
? 1 : 0) << endl
;
219 m_last_error
= _("Error during write. Config may be incomplete.");
225 /// Compares a given databasedatabase from a real device with the
226 /// current config. If not yet configured, initialize with valid
228 void ConfigFile::Enlighten(const Barry::DatabaseDatabase
&db
)
231 // if not fully loaded, we use db as our default list
232 // our defaults are: backup everything, restore everything
235 m_backupList
.clear();
236 m_restoreList
.clear();
238 Barry::DatabaseDatabase::DatabaseArrayType::const_iterator i
=
239 db
.Databases
.begin();
240 for( ; i
!= db
.Databases
.end(); ++i
) {
242 m_backupList
.push_back(i
->Name
);
244 // restore everything except email (which could take ages)
245 // and Handheld Agent (which seems write protected)
246 if( i
->Name
!= Barry::Message::GetDBName() &&
247 i
->Name
!= "Handheld Agent" )
249 m_restoreList
.push_back(i
->Name
);
255 // fill list with all databases from dbdb
256 ConfigFile:: DBListType
& ConfigFile::DBListType::operator=(const DatabaseDatabase
&dbdb
)
261 // copy over all DB names
262 DatabaseDatabase::DatabaseArrayType::const_iterator
263 i
= dbdb
.Databases
.begin(), e
= dbdb
.Databases
.end();
264 for( ; i
!= e
; ++i
) {
271 /// Sets list with new config
272 void ConfigFile::SetBackupList(const DBListType
&list
)
278 void ConfigFile::SetRestoreList(const DBListType
&list
)
280 m_restoreList
= list
;
284 void ConfigFile::SetDeviceName(const std::string
&name
)
292 void ConfigFile::SetBackupPath(const std::string
&path
)
294 if( path
.size() && CheckPath(path
) )
300 void ConfigFile::SetPromptBackupLabel(bool prompt
)
302 m_promptBackupLabel
= prompt
;
305 void ConfigFile::SetAutoSelectAll(bool asa
)
307 m_autoSelectAll
= asa
;
311 //////////////////////////////////////////////////////////////////////////////
312 // GlobalConfigFile class members
314 GlobalConfigFile::GlobalConfigFile()
316 , m_verboseLogging(false)
322 GlobalConfigFile::GlobalConfigFile(const std::string
&appname
)
325 , m_verboseLogging(false)
327 // there can be no spaces in the appname
328 if( m_appname
.find(' ') != std::string::npos
)
329 throw std::logic_error(_("App name must have no spaces."));
335 GlobalConfigFile::~GlobalConfigFile()
339 void GlobalConfigFile::Clear()
345 void GlobalConfigFile::Load()
351 std::ifstream
in(m_filename
.c_str(), std::ios::in
| std::ios::binary
);
357 while( std::getline(in
, line
) ) {
359 std::istringstream
iss(line
);
362 if( keyword
== "last_device" ) {
364 m_lastDevice
.Clear();
367 else if( keyword
== "verbose_logging" ) {
370 m_verboseLogging
= flag
!= 0;
373 // store any other keys as app keys
374 if( keyword
.substr(0, 2) == "X-" ) {
377 std::getline(iss
, line
);
378 m_keymap
[keyword
] = line
;
386 /// Save the current global config, overwriting or creating as needed
387 bool GlobalConfigFile::Save()
389 if( !ConfigFile::CheckPath(m_path
, &m_last_error
) )
392 std::ofstream
out(m_filename
.c_str(), std::ios::out
| std::ios::binary
);
394 m_last_error
= _("Unable to open file for writing: ") + m_filename
;
398 if( !(m_lastDevice
== 0) ) {
399 out
<< "last_device " << m_lastDevice
.Str() << std::endl
;
402 out
<< "verbose_logging " << (m_verboseLogging
? 1 : 0) << std::endl
;
404 // store all app keys
405 keymap_type::const_iterator ci
= m_keymap
.begin();
406 for( ; ci
!= m_keymap
.end(); ++ci
) {
407 out
<< ci
->first
<< " " << ci
->second
<< std::endl
;
411 m_last_error
= _("Error during write. Config may be incomplete.");
417 void GlobalConfigFile::SetKey(const std::string
&key
, const std::string
&value
)
419 if( !m_appname
.size() )
420 throw std::logic_error(_("Cannot use SetKey() without specifying an appname in the constructor."));
422 if( value
.find_first_of("\n\r") != std::string::npos
)
423 throw std::logic_error(_("SetKey values may not contain newline characters."));
425 std::string fullkey
= "X-" + m_appname
+ "-" + key
;
426 m_keymap
[fullkey
] = value
;
429 std::string
GlobalConfigFile::GetKey(const std::string
&key
,
430 const std::string
&default_value
) const
432 if( !m_appname
.size() )
433 throw std::logic_error(_("Cannot use SetKey() without specifying an appname in the constructor."));
435 std::string fullkey
= "X-" + m_appname
+ "-" + key
;
436 keymap_type::const_iterator ci
= m_keymap
.find(fullkey
);
437 if( ci
== m_keymap
.end() )
438 return default_value
;
442 void GlobalConfigFile::SetLastDevice(const Barry::Pin
&pin
)
447 void GlobalConfigFile::SetVerboseLogging(bool verbose
)
449 m_verboseLogging
= verbose
;