6
#include "Environment.h"
8
#include <sys/types.h> // getpwuid, stat, mkdir, getuid
9
#include <sys/stat.h> // stat, mkdir
10
#include <pwd.h> // getpwuid
11
#include <unistd.h> // stat, getuid
17
static bool getbool(xmlpp::Element* el)
19
string val = el->get_child_text()->get_content();
25
string nodename = el->get_name();
26
warning("Unknown value %.*s in node %.*s\n",
27
PFSTR(val), PFSTR(nodename));
31
static void setbool(xmlpp::Element* el, bool value)
33
el->set_child_text(value ? "true" : "false");
37
static int getint(xmlpp::Element* el)
39
string val = el->get_child_text()->get_content();
40
return atoi(val.c_str());
43
static void setint(xmlpp::Element* el, int value)
45
el->set_child_text(stringf::fmt(value));
48
static xmlpp::Element* get_first_el(xmlpp::Element* parent, const std::string& name) throw ()
50
xmlpp::Node::NodeList nl = parent->get_children(name);
54
return dynamic_cast<xmlpp::Element*>(*nl.begin());
57
Config::Config() throw (SystemException, ConsistencyCheckException)
58
: doc_conf(0), _root(0), _general(0), _view(0), _view_empty(0), _view_read(0), _locations(0)
60
struct passwd* udata = getpwuid(getuid());
61
rcfile = udata->pw_dir;
64
struct stat rcfile_stat;
65
if (stat(rcfile.c_str(), &rcfile_stat) == -1)
67
feedback("Creating new configuration file %.*s.\n", PFSTR(rcfile));
69
// Create the configuration from scratch
70
doc_conf = new xmlpp::Document();
71
_root = doc_conf->create_root_node("buffy");
73
if (S_ISDIR(rcfile_stat.st_mode))
74
throw ConsistencyCheckException(rcfile + " already exists and is a directory");
76
if (access(rcfile.c_str(), R_OK) == -1)
77
throw ConsistencyCheckException(rcfile + " already exists and is not readable");
79
feedback("Reading configuration from %.*s.\n", PFSTR(rcfile));
81
// Parse the existing config file
83
// Enable when we'll have a DTD
84
//_xmlparser.set_validate();
85
_xmlparser.set_substitute_entities(); // Resolve/unescape text automatically
86
_xmlparser.parse_file(rcfile);
88
doc_conf = _xmlparser.get_document();
90
throw ConsistencyCheckException("Parser did not parse " + rcfile);
91
} catch (const std::exception& ex) {
92
throw ConsistencyCheckException(string(ex.what()) + " when parsing configuration file " + rcfile);
95
//printf("Init debtags environment; rcdir is %.*s\n", PFSTR(rcdir));
98
xmlpp::Element* Config::el_root() throw ()
101
_root = doc_conf->get_root_node();
105
xmlpp::Element* Config::el_general() throw ()
109
xmlpp::Node::NodeList nl = el_root()->get_children("general");
111
_general = el_root()->add_child("general");
113
_general = dynamic_cast<xmlpp::Element*>(*nl.begin());
118
xmlpp::Element* Config::el_view() throw ()
122
xmlpp::Node::NodeList nl = el_general()->get_children("view");
124
_view = el_general()->add_child("view");
126
_view = dynamic_cast<xmlpp::Element*>(*nl.begin());
131
xmlpp::Element* Config::el_locations() throw ()
135
xmlpp::Node::NodeList nl = el_general()->get_children("locations");
137
_locations = el_general()->add_child("locations");
139
_locations = dynamic_cast<xmlpp::Element*>(*nl.begin());
144
xmlpp::Element* Config::el_view_empty() throw ()
148
xmlpp::Node::NodeList nl = el_view()->get_children("empty");
151
_view_empty = el_view()->add_child("empty");
152
setbool(_view_empty, true);
155
_view_empty = dynamic_cast<xmlpp::Element*>(*nl.begin());
160
xmlpp::Element* Config::el_view_read() throw ()
164
xmlpp::Node::NodeList nl = el_view()->get_children("read");
167
_view_read = el_view()->add_child("read");
168
setbool(_view_read, true);
171
_view_read = dynamic_cast<xmlpp::Element*>(*nl.begin());
176
xmlpp::Element* Config::el_view_important() throw ()
178
if (!_view_important)
180
xmlpp::Node::NodeList nl = el_view()->get_children("important");
183
_view_important = el_view()->add_child("important");
184
setbool(_view_important, true);
187
_view_important = dynamic_cast<xmlpp::Element*>(*nl.begin());
189
return _view_important;
192
xmlpp::Element* Config::el_interval() throw ()
196
xmlpp::Node::NodeList nl = el_general()->get_children("interval");
199
_interval = el_general()->add_child("interval");
200
setint(_interval, 30);
203
_interval = dynamic_cast<xmlpp::Element*>(*nl.begin());
208
xmlpp::Element* Config::el_programs() throw ()
212
xmlpp::Node::NodeList nl = el_general()->get_children("programs");
214
_programs = el_general()->add_child("programs");
216
_programs = dynamic_cast<xmlpp::Element*>(*nl.begin());
222
bool Config::get_view_empty() throw () { return getbool(el_view_empty()); }
223
bool Config::get_view_read() throw () { return getbool(el_view_read()); }
224
bool Config::get_view_important() throw () { return getbool(el_view_important()); }
225
int Config::get_update_interval() throw () { return getint(el_interval()); }
227
void Config::set_view_empty(bool val) throw () { setbool(el_view_empty(), val); }
228
void Config::set_view_read(bool val) throw () { setbool(el_view_read(), val); }
229
void Config::set_view_important(bool val) throw () { setbool(el_view_important(), val); }
230
void Config::set_update_interval(int val) throw () { setint(el_interval(), val); }
233
std::vector<std::string> Config::get_folder_locations() throw ()
235
xmlpp::Node::NodeList nl = el_locations()->get_children("location");
238
struct passwd* udata = getpwuid(getuid());
239
vector<string> deflt;
240
deflt.push_back(string("/var/mail/") + udata->pw_name);
241
deflt.push_back(string(udata->pw_dir) + "/Maildir");
242
deflt.push_back(string(udata->pw_dir) + "/Mail");
243
deflt.push_back(string(udata->pw_dir) + "/mail");
245
for (vector<string>::const_iterator i = deflt.begin();
246
i != deflt.end(); i++)
247
el_locations()->add_child("location")->set_child_text(*i);
254
for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
256
if (xmlpp::Element* e = dynamic_cast<xmlpp::Element*>(*i))
257
res.push_back(e->get_child_text()->get_content());
262
void Config::set_folder_locations(const std::vector<std::string>& locations) throw ()
264
xmlpp::Node::NodeList nl = el_locations()->get_children("location");
266
// First remove all location nodes
267
for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
269
el_locations()->remove_child(*i);
271
// Then add the new ones
272
for (vector<string>::const_iterator i = locations.begin();
273
i != locations.end(); i++)
274
el_locations()->add_child("location")->set_child_text(*i);
278
std::vector<MailProgram> Config::get_mail_programs() throw ()
280
xmlpp::Node::NodeList nl = el_programs()->get_children("mail");
283
std::vector<MailProgram> deflt;
284
deflt.push_back(MailProgram("Mutt", "/usr/bin/x-terminal-emulator -e /usr/bin/mutt -f %p", true));
285
deflt.push_back(MailProgram("Other", "/usr/bin/sample-mail-editor --folder %p"));
287
for (vector<MailProgram>::const_iterator i = deflt.begin();
288
i != deflt.end(); i++)
290
xmlpp::Element* item = el_programs()->add_child("mail");
292
item->set_attribute("selected", "true");
293
xmlpp::Element* val = item->add_child("name");
294
val->set_child_text(i->name());
295
val = item->add_child("command");
296
val->set_child_text(i->command());
303
vector<MailProgram> res;
304
for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
306
if (xmlpp::Element* e = dynamic_cast<xmlpp::Element*>(*i))
309
if (xmlpp::Attribute* at = e->get_attribute("selected"))
310
if (at->get_value() == "true")
314
if (xmlpp::Element* el = get_first_el(e, "name"))
315
name = el->get_child_text()->get_content();
318
if (xmlpp::Element* el = get_first_el(e, "command"))
319
command = el->get_child_text()->get_content();
321
res.push_back(MailProgram(name, command, sel));
327
MailProgram Config::get_selected_mail_program() throw ()
329
vector<MailProgram> progs = get_mail_programs();
330
for (vector<MailProgram>::iterator i = progs.begin();
331
i != progs.end(); i++)
334
return MailProgram();
337
void Config::set_mail_programs(const std::vector<MailProgram>& programs) throw ()
339
xmlpp::Node::NodeList nl = el_programs()->get_children("mail");
341
// First remove all mail nodes
342
for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
344
el_programs()->remove_child(*i);
346
// Then add the new ones
347
for (vector<MailProgram>::const_iterator i = programs.begin();
348
i != programs.end(); i++)
350
xmlpp::Element* item = el_programs()->add_child("mail");
352
item->set_attribute("selected", "true");
353
xmlpp::Element* val = item->add_child("name");
354
val->set_child_text(i->name());
355
val = item->add_child("command");
356
val->set_child_text(i->command());
361
void Config::save() throw (ConsistencyCheckException)
366
feedback("Saving configuration to %.*s.\n", PFSTR(rcfile));
367
doc_conf->write_to_file_formatted(rcfile);
369
feedback("No configuration present: ignoring save request.\n");
370
} catch (const std::exception& ex) {
371
throw ConsistencyCheckException(string(ex.what()) + " when saving configuration file " + rcfile);
375
// vim:set ts=4 sw=4: