presage  0.9.1
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  // config specified by environment overrides system config
125  char *env_profile = getenv("PRESAGE_CONFIG");
126  if (env_profile != NULL) {
127  profiles.push_back(env_profile);
128  } else {
129  // system etc directory
130  profiles.push_back (get_system_etc_dir() + '/' + DefaultProfile::DEFAULT_PROFILE_FILENAME);
131  // installation config directory
132  profiles.push_back (static_cast<std::string>(sysconfdir) + '/' + DefaultProfile::DEFAULT_PROFILE_FILENAME);
133  }
134  // home dir dotfile
135  profiles.push_back (get_user_home_dir() + "/.presage/" + DefaultProfile::DEFAULT_PROFILE_FILENAME);
136  // user specified profile (if any)
137  if (! profilename.empty()) {
138  profiles.push_back(profilename);
139  }
140 
141 
142  // read data from each profile and write it to configuration
143  Profile* profile = 0;
144  for (std::list<std::string>::const_iterator it = profiles.begin();
145  it != profiles.end();
146  it++ ) {
147  delete profile;
148  profile = create_profile_from_xml (*it);
150  profile->read_into_configuration (config);
151  }
152 
153  // remember last profile as writable profile
154  rw_profile = profile;
155 }
156 
157 
159 {
160  std::string result;
161 
162 #if defined(_WIN32)
163  DWORD size;
164  DWORD type;
165  LONG res;
166  HKEY reg_key = NULL;
167  char *dst = NULL;
168 
169  res = RegOpenKeyExA (HKEY_CURRENT_USER, "Software\\Presage", 0,
170  KEY_READ, &reg_key);
171 
172  if (res == ERROR_SUCCESS)
173  {
174  size = 64;
175  dst = (char*) malloc (size);
176 
177  res = RegQueryValueExA (reg_key, "", 0, &type,
178  (LPBYTE) dst, &size);
179  if (res == ERROR_MORE_DATA && type == REG_SZ) {
180  char* tmp_dst = (char*) realloc (dst, size);
181  if (tmp_dst != NULL) {
182  dst = tmp_dst;
183  } else {
184  // realloc failed, try to free and malloc
185  free (dst);
186  dst = (char*) malloc (size);
187  if (dst == NULL) {
188  // malloc failed, cannot recover, just return empty result
189  return result;
190  }
191  }
192  res = RegQueryValueExA (reg_key, "", 0,
193  &type, (LPBYTE) dst,
194  &size);
195  }
196 
197  if (type != REG_SZ || res != ERROR_SUCCESS)
198  {
199  result = ".";
200  }
201  else
202  {
203  result = dst;
204  result += "\\etc";
205  }
206 
207  free (dst);
208  dst = 0;
209  RegCloseKey (reg_key);
210  }
211 
212 #else
213  result = "/etc";
214 #endif
215 
216  return result;
217 }
218 
219 
221 {
222  std::string result;
223 
224 #ifdef _WIN32
225  const char* USERPROFILE = "USERPROFILE";
226  char* value = getenv(USERPROFILE);
227  // check if USERPROFILE env var exists...
228  if (value) {
229  result = value;
230  }
231 #else
232 # ifdef HAVE_PWD_H
233  uid_t me;
234  struct passwd *my_passwd;
235 
236  me = getuid ();
237  my_passwd = getpwuid (me);
238  if (!my_passwd) {
239  // got passwd for user
240  // read home dir from passwd struct
241  result = my_passwd->pw_dir;
242  } else
243  // unable to get passwd struct,
244  // read $HOME env variable
245 # endif // HAVE_PWD_H
246  {
247  const char* HOME = "HOME";
248  char* value = getenv(HOME);
249  // check if HOME env var exists,
250  // assigning a null pointer to a string is
251  // not such a good idea...
252  if (value) {
253  result = value;
254  }
255  }
256 #endif
257 
258  return result;
259 }
260 
261 
268 {
270  bool saveOk = rw_profile->write_to_file ();
271  if (! saveOk) {
272  logger << ERROR << "Failed to save configuration to profile " << endl;
273  }
274 }
275 
277 {
278  // since a Profile is being returned, we know we have a valid
279  // configuration object. Here, we obtain a temporary Configuration
280  // object to read the this ProfileManager configuration. We could
281  // not do this during profile manager construction because no
282  // profile was available at that time.
283  //
284  refresh_config();
285  return config;
286 }
287 
288 void ProfileManager::cache_log_message(Logger<char>::Level level, const std::string& message)
289 {
290  static CachedLogMessage clm;
291  //clm.level = level;
292  clm.message = message;
293  //std::cerr << "Caching message: " << message << std::endl;
294  cached_log_messages.push_back(clm);
295 }
296 
298 {
299  std::list<CachedLogMessage>::const_iterator it = cached_log_messages.begin();
300  while (it != cached_log_messages.end()) {
301  //std::cerr << "Flushing message: " << it->message << std::endl;
302  logger << NOTICE << it->message << endl;
303  it++;
304  }
305  cached_log_messages.clear();
306 }
307 
309 {
310  try {
313  // if no config is available, turn on full logging for profile
314  // manager
315  logger << setlevel("ALL");
316  }
317 
319 }
320 
321 void ProfileManager::set_autopersist (const std::string& value)
322 {
324  logger << INFO << "AUTOPERSIST: " << autopersist_config << endl;
325 }
ProfileManager::loaded_at_least_one_profile
bool loaded_at_least_one_profile
Definition: profileManager.h:93
Logger::NOTICE
@ NOTICE
Definition: logger.h:68
ProfileManager::cache_log_message
void cache_log_message(Logger< char >::Level level, const std::string &message)
Definition: profileManager.cpp:288
DefaultProfile::DEFAULT_PROFILE_FILENAME
static const char * DEFAULT_PROFILE_FILENAME
Definition: defaultProfile.h:68
ProfileManager::create_profile_from_xml
Profile * create_profile_from_xml(const std::string &filename)
Definition: profileManager.cpp:84
Profile
Definition: profile.h:56
profileManager.h
ProfileManager::flush_cached_log_messages
void flush_cached_log_messages()
Definition: profileManager.cpp:297
utility.h
Variable::get_value
std::string get_value() const
Definition: variable.cpp:62
ProfileManager::logger
Logger< char > logger
Definition: profileManager.h:123
Utility::isTrue
static bool isTrue(const char *)
Definition: utility.cpp:107
ProfileManager::LOGGER
static const char * LOGGER
Definition: profileManager.h:82
ProfileManager::refresh_config
void refresh_config()
Definition: profileManager.cpp:308
Profile::file_read_ok
bool file_read_ok() const
Definition: profile.cpp:45
ProfileManager::AUTOPERSIST
static const char * AUTOPERSIST
Definition: profileManager.h:83
Profile::read_into_configuration
void read_into_configuration(Configuration *configuration)
Definition: profile.cpp:50
ProfileManager::autopersist_config
bool autopersist_config
Definition: profileManager.h:121
Profile::write_to_file
bool write_to_file() const
Definition: profile.cpp:96
Profile::read_from_configuration
void read_from_configuration(Configuration *configuration)
Definition: profile.cpp:102
endl
const Logger< _charT, _Traits > & endl(const Logger< _charT, _Traits > &lgr)
Definition: logger.h:278
ProfileManager::get_system_etc_dir
std::string get_system_etc_dir() const
Definition: profileManager.cpp:158
ProfileManager::init_profiles
void init_profiles(const std::string &profilename)
Definition: profileManager.cpp:113
ProfileManager::CachedLogMessage
Definition: profileManager.h:105
ProfileManager::CachedLogMessage::message
std::string message
Definition: profileManager.h:114
Configuration::ConfigurationException
Definition: configuration.h:72
ProfileManager::save_profile
void save_profile() const
Definition: profileManager.cpp:267
Configuration
Definition: configuration.h:36
ProfileManager::get_user_home_dir
std::string get_user_home_dir() const
Definition: profileManager.cpp:220
ProfileManager::ProfileManager
ProfileManager(const std::string="")
Definition: profileManager.cpp:55
configuration.h
ProfileManager::rw_profile
Profile * rw_profile
Definition: profileManager.h:120
ProfileManager::cached_log_messages
std::list< CachedLogMessage > cached_log_messages
Definition: profileManager.h:117
Logger
Definition: logger.h:56
DefaultProfile
Definition: defaultProfile.h:33
HOME
const char HOME
Definition: charsets.h:38
ProfileManager::set_autopersist
void set_autopersist(const std::string &value)
Definition: profileManager.cpp:321
ProfileManager::get_configuration
Configuration * get_configuration()
Definition: profileManager.cpp:276
Configuration::find
Variable * find(const std::string &variable) const
Definition: configuration.cpp:46
setlevel
_SetLevel setlevel(std::string __l)
Manipulator for level.
Definition: logger.h:46
ProfileManager::config
Configuration * config
Definition: profileManager.h:119
ProfileManager::~ProfileManager
~ProfileManager()
Definition: profileManager.cpp:70