~cldunlap1/ubuntu/quantal/buffy/typo-fix

« back to all changes in this revision

Viewing changes to src/Config.cc

  • Committer: Bazaar Package Importer
  • Author(s): Enrico Zini
  • Date: 2004-10-31 14:50:26 UTC
  • Revision ID: james.westby@ubuntu.com-20041031145026-9z3xr78y8j3o5uis
Tags: upstream-0.5
ImportĀ upstreamĀ versionĀ 0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#pragma implementation
 
2
 
 
3
#include "config.h"
 
4
 
 
5
#include "Config.h"
 
6
#include "Environment.h"
 
7
 
 
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
 
12
 
 
13
#include <errno.h>
 
14
 
 
15
using namespace std;
 
16
 
 
17
static bool getbool(xmlpp::Element* el)
 
18
{
 
19
        string val = el->get_child_text()->get_content();
 
20
        if (val == "true")
 
21
                return true;
 
22
        if (val == "false")
 
23
                return false;
 
24
 
 
25
        string nodename = el->get_name();
 
26
        warning("Unknown value %.*s in node %.*s\n",
 
27
                        PFSTR(val), PFSTR(nodename));
 
28
        return false;
 
29
}
 
30
 
 
31
static void setbool(xmlpp::Element* el, bool value)
 
32
{
 
33
        el->set_child_text(value ? "true" : "false");
 
34
}
 
35
 
 
36
 
 
37
static int getint(xmlpp::Element* el)
 
38
{
 
39
        string val = el->get_child_text()->get_content();
 
40
        return atoi(val.c_str());
 
41
}
 
42
 
 
43
static void setint(xmlpp::Element* el, int value)
 
44
{
 
45
        el->set_child_text(stringf::fmt(value));
 
46
}
 
47
 
 
48
static xmlpp::Element* get_first_el(xmlpp::Element* parent, const std::string& name) throw ()
 
49
{
 
50
        xmlpp::Node::NodeList nl = parent->get_children(name);
 
51
        if (nl.empty())
 
52
                return 0;
 
53
        else
 
54
                return dynamic_cast<xmlpp::Element*>(*nl.begin());
 
55
}
 
56
 
 
57
Config::Config() throw (SystemException, ConsistencyCheckException) 
 
58
        : doc_conf(0), _root(0), _general(0), _view(0), _view_empty(0), _view_read(0), _locations(0)
 
59
{
 
60
        struct passwd* udata = getpwuid(getuid());
 
61
        rcfile = udata->pw_dir;
 
62
        rcfile += "/.buffy";
 
63
 
 
64
        struct stat rcfile_stat;
 
65
        if (stat(rcfile.c_str(), &rcfile_stat) == -1)
 
66
        {
 
67
                feedback("Creating new configuration file %.*s.\n", PFSTR(rcfile));
 
68
                
 
69
                // Create the configuration from scratch
 
70
                doc_conf = new xmlpp::Document();
 
71
                _root = doc_conf->create_root_node("buffy");
 
72
        } else {
 
73
                if (S_ISDIR(rcfile_stat.st_mode))
 
74
                        throw ConsistencyCheckException(rcfile + " already exists and is a directory");
 
75
                
 
76
                if (access(rcfile.c_str(), R_OK) == -1)
 
77
                        throw ConsistencyCheckException(rcfile + " already exists and is not readable");
 
78
 
 
79
                feedback("Reading configuration from %.*s.\n", PFSTR(rcfile));
 
80
        
 
81
                // Parse the existing config file
 
82
                try {
 
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);
 
87
                        if (_xmlparser)
 
88
                                doc_conf = _xmlparser.get_document();
 
89
                        else
 
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);
 
93
                }
 
94
        }
 
95
        //printf("Init debtags environment; rcdir is %.*s\n", PFSTR(rcdir));
 
96
}
 
97
 
 
98
xmlpp::Element* Config::el_root() throw ()
 
99
{
 
100
        if (!_root)
 
101
                _root = doc_conf->get_root_node();
 
102
        return _root;
 
103
}
 
104
 
 
105
xmlpp::Element* Config::el_general() throw ()
 
106
{
 
107
        if (!_general)
 
108
        {
 
109
                xmlpp::Node::NodeList nl = el_root()->get_children("general");
 
110
                if (nl.empty())
 
111
                        _general = el_root()->add_child("general");
 
112
                else
 
113
                        _general = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
114
        }
 
115
        return _general;
 
116
}
 
117
 
 
118
xmlpp::Element* Config::el_view() throw ()
 
119
{
 
120
        if (!_view)
 
121
        {
 
122
                xmlpp::Node::NodeList nl = el_general()->get_children("view");
 
123
                if (nl.empty())
 
124
                        _view = el_general()->add_child("view");
 
125
                else
 
126
                        _view = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
127
        }
 
128
        return _view;
 
129
}
 
130
 
 
131
xmlpp::Element* Config::el_locations() throw ()
 
132
{
 
133
        if (!_locations)
 
134
        {
 
135
                xmlpp::Node::NodeList nl = el_general()->get_children("locations");
 
136
                if (nl.empty())
 
137
                        _locations = el_general()->add_child("locations");
 
138
                else
 
139
                        _locations = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
140
        }
 
141
        return _locations;
 
142
}
 
143
 
 
144
xmlpp::Element* Config::el_view_empty() throw ()
 
145
{
 
146
        if (!_view_empty)
 
147
        {
 
148
                xmlpp::Node::NodeList nl = el_view()->get_children("empty");
 
149
                if (nl.empty())
 
150
                {
 
151
                        _view_empty = el_view()->add_child("empty");
 
152
                        setbool(_view_empty, true);
 
153
                }
 
154
                else
 
155
                        _view_empty = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
156
        }
 
157
        return _view_empty;
 
158
}
 
159
 
 
160
xmlpp::Element* Config::el_view_read() throw ()
 
161
{
 
162
        if (!_view_read)
 
163
        {
 
164
                xmlpp::Node::NodeList nl = el_view()->get_children("read");
 
165
                if (nl.empty())
 
166
                {
 
167
                        _view_read = el_view()->add_child("read");
 
168
                        setbool(_view_read, true);
 
169
                }
 
170
                else
 
171
                        _view_read = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
172
        }
 
173
        return _view_read;
 
174
}
 
175
 
 
176
xmlpp::Element* Config::el_view_important() throw ()
 
177
{
 
178
        if (!_view_important)
 
179
        {
 
180
                xmlpp::Node::NodeList nl = el_view()->get_children("important");
 
181
                if (nl.empty())
 
182
                {
 
183
                        _view_important = el_view()->add_child("important");
 
184
                        setbool(_view_important, true);
 
185
                }
 
186
                else
 
187
                        _view_important = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
188
        }
 
189
        return _view_important;
 
190
}
 
191
 
 
192
xmlpp::Element* Config::el_interval() throw ()
 
193
{
 
194
        if (!_interval)
 
195
        {
 
196
                xmlpp::Node::NodeList nl = el_general()->get_children("interval");
 
197
                if (nl.empty())
 
198
                {
 
199
                        _interval = el_general()->add_child("interval");
 
200
                        setint(_interval, 30);
 
201
                }
 
202
                else
 
203
                        _interval = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
204
        }
 
205
        return _interval;
 
206
}
 
207
 
 
208
xmlpp::Element* Config::el_programs() throw ()
 
209
{
 
210
        if (!_programs)
 
211
        {
 
212
                xmlpp::Node::NodeList nl = el_general()->get_children("programs");
 
213
                if (nl.empty())
 
214
                        _programs = el_general()->add_child("programs");
 
215
                else
 
216
                        _programs = dynamic_cast<xmlpp::Element*>(*nl.begin());
 
217
        }
 
218
        return _programs;
 
219
}
 
220
 
 
221
 
 
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()); }
 
226
 
 
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); }
 
231
 
 
232
 
 
233
std::vector<std::string> Config::get_folder_locations() throw ()
 
234
{
 
235
        xmlpp::Node::NodeList nl = el_locations()->get_children("location");
 
236
        if (nl.empty())
 
237
        {
 
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");
 
244
 
 
245
                for (vector<string>::const_iterator i = deflt.begin();
 
246
                                i != deflt.end(); i++)
 
247
                        el_locations()->add_child("location")->set_child_text(*i);
 
248
 
 
249
                return deflt;
 
250
        }
 
251
        else
 
252
        {
 
253
                vector<string> res;
 
254
                for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
 
255
                                i != nl.end(); i++)
 
256
                        if (xmlpp::Element* e = dynamic_cast<xmlpp::Element*>(*i))
 
257
                                res.push_back(e->get_child_text()->get_content());
 
258
                return res;
 
259
        }
 
260
}
 
261
 
 
262
void Config::set_folder_locations(const std::vector<std::string>& locations) throw ()
 
263
{
 
264
        xmlpp::Node::NodeList nl = el_locations()->get_children("location");
 
265
 
 
266
        // First remove all location nodes
 
267
        for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
 
268
                        i != nl.end(); i++)
 
269
                el_locations()->remove_child(*i);
 
270
 
 
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);
 
275
}
 
276
 
 
277
 
 
278
std::vector<MailProgram> Config::get_mail_programs() throw ()
 
279
{
 
280
        xmlpp::Node::NodeList nl = el_programs()->get_children("mail");
 
281
        if (nl.empty())
 
282
        {
 
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"));
 
286
 
 
287
                for (vector<MailProgram>::const_iterator i = deflt.begin();
 
288
                                i != deflt.end(); i++)
 
289
                {
 
290
                        xmlpp::Element* item = el_programs()->add_child("mail");
 
291
                        if (i->selected())
 
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());
 
297
                }
 
298
 
 
299
                return deflt;
 
300
        }
 
301
        else
 
302
        {
 
303
                vector<MailProgram> res;
 
304
                for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
 
305
                                i != nl.end(); i++)
 
306
                        if (xmlpp::Element* e = dynamic_cast<xmlpp::Element*>(*i))
 
307
                        {
 
308
                                bool sel = false;
 
309
                                if (xmlpp::Attribute* at = e->get_attribute("selected"))
 
310
                                        if (at->get_value() == "true")
 
311
                                                sel = true;
 
312
 
 
313
                                string name;
 
314
                                if (xmlpp::Element* el = get_first_el(e, "name"))
 
315
                                        name = el->get_child_text()->get_content();
 
316
 
 
317
                                string command;
 
318
                                if (xmlpp::Element* el = get_first_el(e, "command"))
 
319
                                        command = el->get_child_text()->get_content();
 
320
                                
 
321
                                res.push_back(MailProgram(name, command, sel));
 
322
                        }
 
323
                return res;
 
324
        }
 
325
}
 
326
 
 
327
MailProgram Config::get_selected_mail_program() throw ()
 
328
{
 
329
        vector<MailProgram> progs = get_mail_programs();
 
330
        for (vector<MailProgram>::iterator i = progs.begin();
 
331
                        i != progs.end(); i++)
 
332
                if (i->selected())
 
333
                        return *i;
 
334
        return MailProgram();
 
335
}
 
336
 
 
337
void Config::set_mail_programs(const std::vector<MailProgram>& programs) throw ()
 
338
{
 
339
        xmlpp::Node::NodeList nl = el_programs()->get_children("mail");
 
340
 
 
341
        // First remove all mail nodes
 
342
        for (xmlpp::Node::NodeList::const_iterator i = nl.begin();
 
343
                        i != nl.end(); i++)
 
344
                el_programs()->remove_child(*i);
 
345
 
 
346
        // Then add the new ones
 
347
        for (vector<MailProgram>::const_iterator i = programs.begin();
 
348
                        i != programs.end(); i++)
 
349
        {
 
350
                xmlpp::Element* item = el_programs()->add_child("mail");
 
351
                if (i->selected())
 
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());
 
357
        }
 
358
}
 
359
 
 
360
 
 
361
void Config::save() throw (ConsistencyCheckException)
 
362
{
 
363
        try {
 
364
                if (doc_conf)
 
365
                {
 
366
                        feedback("Saving configuration to %.*s.\n", PFSTR(rcfile));
 
367
                        doc_conf->write_to_file_formatted(rcfile);
 
368
                } else
 
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);
 
372
        }
 
373
}
 
374
 
 
375
// vim:set ts=4 sw=4: