presage
0.8.7
|
00001 00002 /****************************************************** 00003 * Presage, an extensible predictive text entry system 00004 * --------------------------------------------------- 00005 * 00006 * Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk> 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License along 00019 with this program; if not, write to the Free Software Foundation, Inc., 00020 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00021 * 00022 **********(*)*/ 00023 00024 00025 #include "profileManager.h" 00026 #include "utility.h" // isYes isNo isTrue isFalse utility function 00027 #include "dirs.h" // sysconfdir macro define 00028 #include "configuration.h" 00029 00030 #ifdef HAVE_PWD_H 00031 # include <pwd.h> 00032 #endif 00033 00034 #if HAVE_UNISTD_H 00035 # include <sys/types.h> 00036 # include <unistd.h> 00037 #endif 00038 00039 #if HAVE_STDLIB_H 00040 # include <stdlib.h> 00041 #endif 00042 00043 #if defined(_WIN32) 00044 # include <windows.h> 00045 #endif 00046 00047 const char* ProfileManager::LOGGER = "Presage.ProfileManager.LOGGER"; 00048 const char* ProfileManager::AUTOPERSIST = "Presage.ProfileManager.AUTOPERSIST"; 00049 00055 ProfileManager::ProfileManager(const std::string profilename) 00056 : logger("ProfileManager", std::cerr) 00057 { 00058 config = new Configuration(); 00059 loaded_at_least_one_profile = false; 00060 rw_profile = 0; 00061 autopersist_config = false; 00062 00063 init_profiles (profilename); 00064 } 00065 00066 00070 ProfileManager::~ProfileManager() 00071 { 00072 flush_cached_log_messages (); 00073 00074 set_autopersist (config->find (AUTOPERSIST)->get_value ()); 00075 if (autopersist_config) { 00076 save_profile (); 00077 } 00078 00079 delete config; 00080 delete rw_profile; 00081 } 00082 00083 00084 Profile* ProfileManager::create_profile_from_xml (const std::string& filename) 00085 { 00086 Profile* profile = new Profile (filename); 00087 00088 std::string message; 00089 if (profile->file_read_ok ()) { 00090 // logger has not been init'd with configuration, because no 00091 // profile is known yet, hence caching this logging item, 00092 // which will be flushed when configuration is finally read in 00093 // 00094 message = "Loaded profile: " + filename; 00095 00096 cache_log_message(logger.NOTICE, message); 00097 00098 } else { 00099 // logger has not been init'd with configuration, because no 00100 // profile is known yet, hence caching this logging item, 00101 // which will be flushed when configuration is finally read in 00102 // 00103 message = "Failed to load profile: " + filename; 00104 00105 cache_log_message(logger.NOTICE, message); 00106 00107 } 00108 00109 return profile; 00110 } 00111 00112 00113 void ProfileManager::init_profiles (const std::string& profilename) 00114 { 00115 std::list<std::string> profiles; 00116 00117 { 00118 // load default profile values 00119 DefaultProfile default_profile (""); 00120 default_profile.read_into_configuration (config); 00121 } 00122 00123 00124 // system etc directory 00125 profiles.push_back (get_system_etc_dir() + '/' + DefaultProfile::DEFAULT_PROFILE_FILENAME); 00126 // installation config directory 00127 profiles.push_back (static_cast<std::string>(sysconfdir) + '/' + DefaultProfile::DEFAULT_PROFILE_FILENAME); 00128 // home dir dotfile 00129 profiles.push_back (get_user_home_dir() + '/' + '.' + DefaultProfile::DEFAULT_PROFILE_FILENAME); 00130 // user specified profile (if any) 00131 if (! profilename.empty()) { 00132 profiles.push_back(profilename); 00133 } 00134 00135 00136 // read data from each profile and write it to configuration 00137 Profile* profile = 0; 00138 for (std::list<std::string>::const_iterator it = profiles.begin(); 00139 it != profiles.end(); 00140 it++ ) { 00141 delete profile; 00142 profile = create_profile_from_xml (*it); 00143 loaded_at_least_one_profile = loaded_at_least_one_profile || profile->file_read_ok (); 00144 profile->read_into_configuration (config); 00145 } 00146 00147 // remember last profile as writable profile 00148 rw_profile = profile; 00149 } 00150 00151 00152 std::string ProfileManager::get_system_etc_dir() const 00153 { 00154 std::string result; 00155 00156 #if defined(_WIN32) 00157 DWORD size; 00158 DWORD type; 00159 LONG res; 00160 HKEY reg_key = NULL; 00161 char *dst = NULL; 00162 00163 res = RegOpenKeyExA (HKEY_CURRENT_USER, "Software", 0, 00164 KEY_READ, ®_key); 00165 00166 if (res == ERROR_SUCCESS) { 00167 res = RegOpenKeyExA (reg_key, "Presage", 0, 00168 KEY_READ, ®_key); 00169 } 00170 00171 if (res != ERROR_SUCCESS) { 00172 reg_key = (HKEY) INVALID_HANDLE_VALUE; 00173 return "."; 00174 } 00175 00176 00177 size = 64; 00178 dst = (char*) malloc (size); 00179 00180 res = RegQueryValueExA (reg_key, "", 0, &type, 00181 (LPBYTE) dst, &size); 00182 if (res == ERROR_MORE_DATA && type == REG_SZ) { 00183 dst = (char*) realloc (dst, size); 00184 res = RegQueryValueExA (reg_key, "", 0, &type, 00185 (LPBYTE) dst, &size); 00186 } 00187 00188 if (type != REG_SZ || res != ERROR_SUCCESS) { 00189 free (dst); 00190 dst = 0; 00191 } 00192 00193 result = dst; 00194 result += "\\etc"; 00195 free (dst); 00196 #else 00197 result = "/etc"; 00198 #endif 00199 00200 return result; 00201 } 00202 00203 00204 std::string ProfileManager::get_user_home_dir() const 00205 { 00206 std::string result; 00207 00208 #ifdef _WIN32 00209 const char* USERPROFILE = "USERPROFILE"; 00210 char* value = getenv(USERPROFILE); 00211 // check if USERPROFILE env var exists... 00212 if (value) { 00213 result = value; 00214 } 00215 #else 00216 # ifdef HAVE_PWD_H 00217 uid_t me; 00218 struct passwd *my_passwd; 00219 00220 me = getuid (); 00221 my_passwd = getpwuid (me); 00222 if (!my_passwd) { 00223 // got passwd for user 00224 // read home dir from passwd struct 00225 result = my_passwd->pw_dir; 00226 } else 00227 // unable to get passwd struct, 00228 // read $HOME env variable 00229 # endif // HAVE_PWD_H 00230 { 00231 const char* HOME = "HOME"; 00232 char* value = getenv(HOME); 00233 // check if HOME env var exists, 00234 // assigning a null pointer to a string is 00235 // not such a good idea... 00236 if (value) { 00237 result = value; 00238 } 00239 } 00240 #endif 00241 00242 return result; 00243 } 00244 00245 00251 void ProfileManager::save_profile() const 00252 { 00253 rw_profile->read_from_configuration (config); 00254 bool saveOk = rw_profile->write_to_file (); 00255 if (! saveOk) { 00256 logger << ERROR << "Failed to save configuration to profile " << endl; 00257 } 00258 } 00259 00260 Configuration* ProfileManager::get_configuration() 00261 { 00262 // since a Profile is being returned, we know we have a valid 00263 // configuration object. Here, we obtain a temporary Configuration 00264 // object to read the this ProfileManager configuration. We could 00265 // not do this during profile manager construction because no 00266 // profile was available at that time. 00267 // 00268 refresh_config(); 00269 return config; 00270 } 00271 00272 void ProfileManager::cache_log_message(Logger<char>::Level level, const std::string& message) 00273 { 00274 static CachedLogMessage clm; 00275 //clm.level = level; 00276 clm.message = message; 00277 //std::cerr << "Caching message: " << message << std::endl; 00278 cached_log_messages.push_back(clm); 00279 } 00280 00281 void ProfileManager::flush_cached_log_messages() 00282 { 00283 std::list<CachedLogMessage>::const_iterator it = cached_log_messages.begin(); 00284 while (it != cached_log_messages.end()) { 00285 //std::cerr << "Flushing message: " << it->message << std::endl; 00286 logger << NOTICE << it->message << endl; 00287 it++; 00288 } 00289 cached_log_messages.clear(); 00290 } 00291 00292 void ProfileManager::refresh_config() 00293 { 00294 try { 00295 logger << setlevel(config->find (LOGGER)->get_value()); 00296 } catch (Configuration::ConfigurationException& ex) { 00297 // if no config is available, turn on full logging for profile 00298 // manager 00299 logger << setlevel("ALL"); 00300 } 00301 00302 flush_cached_log_messages(); 00303 } 00304 00305 void ProfileManager::set_autopersist (const std::string& value) 00306 { 00307 autopersist_config = Utility::isTrue (value); 00308 logger << INFO << "AUTOPERSIST: " << autopersist_config << endl; 00309 }