presage  0.9.2~beta
profileManager.cpp
Go to the documentation of this file.
1 
2 /******************************************************
3  * Presage, an extensible predictive text entry system
4  * ---------------------------------------------------
5  *
6  * Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  **********(*)*/
23 
24 
25 #include "profileManager.h"
26 #include "utility.h" // isYes isNo isTrue isFalse utility function
27 #include "dirs.h" // sysconfdir macro define
28 #include "configuration.h"
29 
30 #ifdef HAVE_PWD_H
31 # include <pwd.h>
32 #endif
33 
34 #if HAVE_UNISTD_H
35 # include <sys/types.h>
36 # include <unistd.h>
37 #endif
38 
39 #if HAVE_STDLIB_H
40 # include <stdlib.h>
41 #endif
42 
43 #if defined(_WIN32)
44 # include <windows.h>
45 #endif
46 
47 const char* ProfileManager::LOGGER = "Presage.ProfileManager.LOGGER";
48 const char* ProfileManager::AUTOPERSIST = "Presage.ProfileManager.AUTOPERSIST";
49 
55 ProfileManager::ProfileManager(const std::string profilename)
56  : logger("ProfileManager", std::cerr)
57 {
58  config = new Configuration();
60  rw_profile = 0;
61  autopersist_config = false;
62 
63  init_profiles (profilename);
64 }
65 
66 
71 {
73 
75  if (autopersist_config) {
76  save_profile ();
77  }
78 
79  delete config;
80  delete rw_profile;
81 }
82 
83 
84 Profile* ProfileManager::create_profile_from_xml (const std::string& filename)
85 {
86  Profile* profile = new Profile (filename);
87 
88  std::string message;
89  if (profile->file_read_ok ()) {
90  // logger has not been init'd with configuration, because no
91  // profile is known yet, hence caching this logging item,
92  // which will be flushed when configuration is finally read in
93  //
94  message = "Loaded profile: " + filename;
95 
97 
98  } else {
99  // logger has not been init'd with configuration, because no
100  // profile is known yet, hence caching this logging item,
101  // which will be flushed when configuration is finally read in
102  //
103  message = "Failed to load profile: " + filename;
104 
105  cache_log_message(logger.NOTICE, message);
106 
107  }
108 
109  return profile;
110 }
111 
112 
113 void ProfileManager::init_profiles (const std::string& profilename)
114 {
115  std::list<std::string> profiles;
116 
117  {
118  // load default profile values
119  DefaultProfile default_profile ("");
120  default_profile.read_into_configuration (config);
121  }
122 
123 
124  // system etc directory
125  profiles.push_back (get_system_etc_dir() + '/' + DefaultProfile::DEFAULT_PROFILE_FILENAME);
126  // installation config directory
127  profiles.push_back (static_cast<std::string>(sysconfdir) + '/' + DefaultProfile::DEFAULT_PROFILE_FILENAME);
128  // home dir dotfile
129  profiles.push_back (get_user_home_dir() + "/.presage/" + DefaultProfile::DEFAULT_PROFILE_FILENAME);
130  // user specified profile (if any)
131  if (! profilename.empty()) {
132  profiles.push_back(profilename);
133  }
134 
135 
136  // read data from each profile and write it to configuration
137  Profile* profile = 0;
138  for (std::list<std::string>::const_iterator it = profiles.begin();
139  it != profiles.end();
140  it++ ) {
141  delete profile;
142  profile = create_profile_from_xml (*it);
144  profile->read_into_configuration (config);
145  }
146 
147  // remember last profile as writable profile
148  rw_profile = profile;
149 }
150 
151 
153 {
154  std::string result;
155 
156 #if defined(_WIN32)
157  DWORD size;
158  DWORD type;
159  LONG res;
160  HKEY reg_key = NULL;
161  char *dst = NULL;
162 
163  res = RegOpenKeyExA (HKEY_CURRENT_USER, "Software\\Presage", 0,
164  KEY_READ, &reg_key);
165 
166  if (res == ERROR_SUCCESS)
167  {
168  size = 64;
169  dst = (char*) malloc (size);
170 
171  res = RegQueryValueExA (reg_key, "", 0, &type,
172  (LPBYTE) dst, &size);
173  if (res == ERROR_MORE_DATA && type == REG_SZ) {
174  char* tmp_dst = (char*) realloc (dst, size);
175  if (tmp_dst != NULL) {
176  dst = tmp_dst;
177  } else {
178  // realloc failed, try to free and malloc
179  free (dst);
180  dst = (char*) malloc (size);
181  if (dst == NULL) {
182  // malloc failed, cannot recover, just return empty result
183  return result;
184  }
185  }
186  res = RegQueryValueExA (reg_key, "", 0,
187  &type, (LPBYTE) dst,
188  &size);
189  }
190 
191  if (type != REG_SZ || res != ERROR_SUCCESS)
192  {
193  result = ".";
194  }
195  else
196  {
197  result = dst;
198  result += "\\etc";
199  }
200 
201  free (dst);
202  dst = 0;
203  RegCloseKey (reg_key);
204  }
205 
206 #else
207  result = "/etc";
208 #endif
209 
210  return result;
211 }
212 
213 
215 {
216  std::string result;
217 
218 #ifdef _WIN32
219  const char* USERPROFILE = "USERPROFILE";
220  char* value = getenv(USERPROFILE);
221  // check if USERPROFILE env var exists...
222  if (value) {
223  result = value;
224  }
225 #else
226 # ifdef HAVE_PWD_H
227  uid_t me;
228  struct passwd *my_passwd;
229 
230  me = getuid ();
231  my_passwd = getpwuid (me);
232  if (!my_passwd) {
233  // got passwd for user
234  // read home dir from passwd struct
235  result = my_passwd->pw_dir;
236  } else
237  // unable to get passwd struct,
238  // read $HOME env variable
239 # endif // HAVE_PWD_H
240  {
241  const char* HOME = "HOME";
242  char* value = getenv(HOME);
243  // check if HOME env var exists,
244  // assigning a null pointer to a string is
245  // not such a good idea...
246  if (value) {
247  result = value;
248  }
249  }
250 #endif
251 
252  return result;
253 }
254 
255 
262 {
264  bool saveOk = rw_profile->write_to_file ();
265  if (! saveOk) {
266  logger << ERROR << "Failed to save configuration to profile " << endl;
267  }
268 }
269 
271 {
272  // since a Profile is being returned, we know we have a valid
273  // configuration object. Here, we obtain a temporary Configuration
274  // object to read the this ProfileManager configuration. We could
275  // not do this during profile manager construction because no
276  // profile was available at that time.
277  //
278  refresh_config();
279  return config;
280 }
281 
282 void ProfileManager::cache_log_message(Logger<char>::Level level, const std::string& message)
283 {
284  static CachedLogMessage clm;
285  //clm.level = level;
286  clm.message = message;
287  //std::cerr << "Caching message: " << message << std::endl;
288  cached_log_messages.push_back(clm);
289 }
290 
292 {
293  std::list<CachedLogMessage>::const_iterator it = cached_log_messages.begin();
294  while (it != cached_log_messages.end()) {
295  //std::cerr << "Flushing message: " << it->message << std::endl;
296  logger << NOTICE << it->message << endl;
297  it++;
298  }
299  cached_log_messages.clear();
300 }
301 
303 {
304  try {
307  // if no config is available, turn on full logging for profile
308  // manager
309  logger << setlevel("ALL");
310  }
311 
313 }
314 
315 void ProfileManager::set_autopersist (const std::string& value)
316 {
318  logger << INFO << "AUTOPERSIST: " << autopersist_config << endl;
319 }
Definition: logger.h:56
static const char * DEFAULT_PROFILE_FILENAME
Configuration * config
Configuration * get_configuration()
std::string get_system_etc_dir() const
Logger< char > logger
static const char * LOGGER
void save_profile() const
std::list< CachedLogMessage > cached_log_messages
_SetLevel setlevel(std::string __l)
Manipulator for level.
Definition: logger.h:46
Profile * rw_profile
const char HOME
Definition: charsets.h:38
Variable * find(const std::string &variable) const
bool file_read_ok() const
Definition: profile.cpp:45
bool loaded_at_least_one_profile
bool write_to_file() const
Definition: profile.cpp:96
void read_from_configuration(Configuration *configuration)
Definition: profile.cpp:102
void set_autopersist(const std::string &value)
std::string get_value() const
Definition: variable.cpp:62
void init_profiles(const std::string &profilename)
void cache_log_message(Logger< char >::Level level, const std::string &message)
static const char * AUTOPERSIST
void read_into_configuration(Configuration *configuration)
Definition: profile.cpp:50
static bool isTrue(const char *)
Definition: utility.cpp:107
void flush_cached_log_messages()
Profile * create_profile_from_xml(const std::string &filename)
ProfileManager(const std::string="")
const Logger< _charT, _Traits > & endl(const Logger< _charT, _Traits > &lgr)
Definition: logger.h:278
std::string get_user_home_dir() const