]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/protected/Class/ConfigurationManager.php
baculum: Assign Baculum copyright to Kern Sibbald
[bacula/bacula] / gui / baculum / protected / Class / ConfigurationManager.php
1 <?php
2 /*
3  * Bacula(R) - The Network Backup Solution
4  * Baculum   - Bacula web interface
5  *
6  * Copyright (C) 2013-2016 Kern Sibbald
7  *
8  * The main author of Baculum is Marcin Haba.
9  * The original author of Bacula is Kern Sibbald, with contributions
10  * from many others, a complete list can be found in the file AUTHORS.
11  *
12  * You may use this file and others of this release according to the
13  * license defined in the LICENSE file, which includes the Affero General
14  * Public License, v3.0 ("AGPLv3") and some additional permissions and
15  * terms pursuant to its AGPLv3 Section 7.
16  *
17  * This notice must be preserved when any source code is
18  * conveyed and/or propagated.
19  *
20  * Bacula(R) is a registered trademark of Kern Sibbald.
21  */
22
23 Prado::using('Application.Class.Miscellaneous');
24
25 /**
26  * Manage application configuration.
27  * Module is responsible for get/set application config data like:
28  * read/write application config and usersfiles, get application language
29  * and others.
30  *
31  * @author Marcin Haba <marcin.haba@bacula.pl>
32  */
33 class ConfigurationManager extends TModule
34 {
35
36         /**
37          * Application config file path
38          */
39         const CONFIG_FILE = 'Application.Data.settings';
40
41         /**
42          * Users login and password file for HTTP Basic auth.
43          */
44         const USERS_FILE = 'Application.Data.baculum';
45
46         /**
47          * User name allowed characters pattern
48          */
49         const USER_PATTERN = '[a-zA-Z0-9]+';
50
51         /**
52          * PostgreSQL default params
53          */
54         const PGSQL = 'pgsql';
55         const PGSQL_NAME = 'PostgreSQL';
56         const PGSQL_PORT = 5432;
57
58         /**
59          * MySQL default params
60          */
61         const MYSQL = 'mysql';
62         const MYSQL_NAME = 'MySQL';
63         const MYSQL_PORT = 3306;
64
65         /**
66          * SQLite default params
67          */
68         const SQLITE = 'sqlite';
69         const SQLITE_NAME = 'SQLite';
70         const SQLITE_PORT = null;
71
72         /**
73          * Default application language
74          */
75         const DEFAULT_LANGUAGE = 'en';
76
77         /**
78          * Get database name by database type (short name).
79          *
80          * @access public
81          * @param string $type database type ('pgsql', 'mysql' ...)
82          * @return mixed database name or null if database name not found
83          */
84         public function getDbNameByType($type) {
85                 $type = (string) $type;
86                 switch($type) {
87                         case self::PGSQL: $db_name = self::PGSQL_NAME; break;
88                         case self::MYSQL: $db_name = self::MYSQL_NAME; break;
89                         case self::SQLITE: $db_name = self::SQLITE_NAME; break;
90                         default: $db_name = null; break;
91                 }
92                 return $db_name;
93         }
94
95         /**
96          * Check if given database type is PostgreSQL type.
97          *
98          * @access public
99          * @param string $type database type ('pgsql', 'mysql' ...)
100          * @return boolean true if database type is PostgreSQL, otherwise false
101          */
102         public function isPostgreSQLType($type) {
103                 return ($type === self::PGSQL);
104         }
105
106         /**
107          * Check if given database type is MySQL type.
108          *
109          * @access public
110          * @param string $type database type ('pgsql', 'mysql' ...)
111          * @return boolean true if database type is MySQL, otherwise false
112          */
113         public function isMySQLType($type) {
114                 return ($type === self::MYSQL);
115         }
116
117         /**
118          * Check if given database type is SQLite type.
119          *
120          * @access public
121          * @param string $type database type ('sqlite', 'mysql' ...)
122          * @return boolean true if database type is SQLite, otherwise false
123          */
124         public function isSQLiteType($type) {
125                 return ($type === self::SQLITE);
126         }
127
128         /**
129          * Get currently set application language short name.
130          * If no language set then default language is taken.
131          *
132          * @access public
133          * @return string lanuage short name
134          */
135         public function getLanguage() {
136                 $language = self::DEFAULT_LANGUAGE;
137                 if ($this->isApplicationConfig() === true) {
138                         $config = self::getApplicationConfig();
139                         if (array_key_exists('lang', $config['baculum'])) {
140                                 $language = $config['baculum']['lang'];
141                         }
142                 }
143                 return $language;
144         }
145
146         /**
147          * Save application configuration.
148          *
149          * @access public
150          * @param array $config structure of config file params
151          * @return boolean true if config save is successfully, false if config save is failure
152          */
153         public function setApplicationConfig(array $config) {
154                 $cfg_file = Prado::getPathOfNamespace(self::CONFIG_FILE, '.conf');
155                 return ($this->Application->getModule('misc')->writeINIFile($cfg_file, $config) != false);
156         }
157
158         /**
159          * Get application configuration.
160          *
161          * @access public
162          * @return array application configuration
163          */
164         public static function getApplicationConfig() {
165                 $cfg_file = Prado::getPathOfNamespace(self::CONFIG_FILE, '.conf');
166                 return Miscellaneous::parseINIFile($cfg_file);
167         }
168
169         /**
170          * Check if application configuration file exists.
171          *
172          * @access public
173          * @return boolean true if file exists, otherwise false
174          */
175         public function isApplicationConfig() {
176                 return file_exists(Prado::getPathOfNamespace(self::CONFIG_FILE, '.conf'));
177         }
178
179         /**
180          * Get user name allowed characters pattern
181          *
182          * @access public
183          * @return string user name pattern
184          */
185         public function getUserPattern() {
186                 return self::USER_PATTERN;
187         }
188
189         /**
190          * Get encrypted password to use in HTTP Basic auth.
191          *
192          * @access public
193          * @param string $password plain text password
194          * @return string encrypted password
195          */
196         public function getCryptedPassword($password) {
197                 $enc_pwd = crypt($password, base64_encode($password));
198                 return $enc_pwd;
199         }
200
201         /**
202          * Save user to users configuration file.
203          *
204          * @access public
205          * @param string $user username
206          * @param string $password user's password
207          * @param boolean $first_usage determine if it is first saved user during first Baculum run
208          * @param mixed $old_user previous username before change
209          * @return boolean true if user saved successfully, otherwise false
210          */
211         public function setUsersConfig($user, $password, $first_usage = false, $old_user = null) {
212                 if ($first_usage === true) {
213                         $this->clearUsersConfig();
214                 }
215
216                 $all_users = $this->getAllUsers();
217                 $password = $this->getCryptedPassword($password);
218
219                 $userExists = array_key_exists($user, $all_users);
220
221
222                 if ($userExists === true) {
223                         // update user password;
224                         $all_users[$user] = $password;
225                 }
226
227                 if (!is_null($old_user) && $old_user !== $user) {
228                         // delete old username with password from configuration file
229                         if (array_key_exists($old_user, $all_users)) {
230                                 unset($all_users[$old_user]);
231                         }
232                 }
233
234                 // add new user if does not exist
235                 if ($userExists === false) {
236                         $all_users[$user] = $password;
237                 }
238
239                 $result = $this->saveUserConfig($all_users);
240                 return $result;
241         }
242
243         /**
244          * Read all users from HTTP Basic users file.
245          * Returned value is associative array with usernames as keys
246          * and encrypted passwords as values.
247          *
248          * @access public
249          * @return array users/passwords list
250          */
251         public function getAllUsers() {
252                 $all_users = array();
253                 if ($this->isUsersConfig() === true) {
254                         $users_file = Prado::getPathOfNamespace(self::USERS_FILE, '.users');
255                         $users = file($users_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
256
257                         for($i = 0; $i < count($users); $i++) {
258                                 if (preg_match("/^(?P<user>\S+)\:(?P<hash>\S+)$/", $users[$i], $match) === 1) {
259                                         $all_users[$match['user']] = $match['hash'];
260                                 }
261                         }
262                 }
263                 return $all_users;
264         }
265
266         /**
267          * Save HTTP Basic users file.
268          * Given parameter is associative array with usernames as keys
269          * and encrypted passwords as values.
270          *
271          * @access public
272          * @param array $all_users users/passwords list
273          * @return boolean true if users file saved successfully, otherwise false
274          */
275         public function saveUserConfig($all_users) {
276                 $users = array();
277                 foreach ($all_users as $user => $pwd) {
278                         $users[] = "$user:$pwd";
279                 }
280                 $users_file = Prado::getPathOfNamespace(self::USERS_FILE, '.users');
281                 $usersToFile = implode("\n", $users);
282                 $old_umask = umask(0);
283                 umask(0077);
284                 $result = file_put_contents($users_file, $usersToFile) !== false;
285                 umask($old_umask);
286                 return $result;
287         }
288
289         /**
290          * Remove single user from HTTP Basic users file.
291          * Note, this method saves config file if username was existed
292          * before removing.
293          *
294          * @access public
295          * @param string $username user name to remove
296          * @return boolean true if users file saved successfully, otherwise false
297          */
298         public function removeUser($username) {
299                 $result = false;
300                 $all_users = $this->getAllUsers();
301                 if (array_key_exists($username, $all_users)) {
302                         unset($all_users[$username]);
303                         $result = $this->saveUserConfig($all_users);
304                 }
305                 return $result;
306         }
307
308         /**
309          * Check if users configuration file exists.
310          *
311          * @access public
312          * @return boolean true if file exists, otherwise false
313          */
314         public function isUsersConfig() {
315                 return file_exists(Prado::getPathOfNamespace(self::USERS_FILE, '.users'));
316         }
317
318         /**
319          * Clear all content of users file.
320          *
321          * @access public
322          * @return boolean true if file cleared successfully, otherwise false
323          */
324         public function clearUsersConfig() {
325                 $users_file = Prado::getPathOfNamespace(self::USERS_FILE, '.users');
326                 $result = file_put_contents($users_file, '') !== false;
327                 return $result;
328         }
329
330         /**
331          * Log in as specific user.
332          *
333          * Note, usually after this method call there required is using exit() just
334          * after method execution. Otherwise the HTTP redirection may be canceled on some
335          * web servers.
336          *
337          * @access public
338          * @param string $http_protocol 'http' or 'https' value
339          * @param string $host hostname without port, for example: my.own.host or localhost
340          * @param integer $port port number on which listens web server
341          * @param string $user user name to log in
342          * @param string $string plain text user's password
343          * @return none
344          */
345         public function switchToUser($http_protocol, $host, $port, $user, $password) {
346                 $url_prefix = $this->Application->getModule('friendly-url')->getUrlPrefix();
347                 $location = sprintf("%s://%s:%s@%s:%d%s", $http_protocol, $user, $password, $host, $port, $url_prefix);
348                 $refresh_url = sprintf("%s://%s:%d%s", $http_protocol, $host, $port, $url_prefix);
349
350                 /**
351                  * Refresh page is required due to lack of auth data in $_SERVER superglobal array
352                  * after re-login by URI.
353                  */
354                 $_SESSION['refresh_page'] = $refresh_url;
355
356                 // Log in by header
357                 header("Location: $location");
358         }
359
360         /**
361          * Get (pseudo)random string.
362          *
363          * Useful for log out user from HTTP Basic auth by providing random password.
364          *
365          * @access public
366          * @return string random 62 characters string from range [a-zA-Z0-9]
367          */
368         public function getRandomString() {
369                 $characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
370                 $rand_string = str_shuffle($characters);
371                 return $rand_string;
372         }
373 }
374 ?>