PageRenderTime 23ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/psm/Module/Install/Controller/InstallController.php

https://gitlab.com/billyprice1/phpservermon
PHP | 352 lines | 240 code | 38 blank | 74 comment | 42 complexity | 2edcb1f9c04861d44e4ed5ab9a2fda30 MD5 | raw file
  1. <?php
  2. /**
  3. * PHP Server Monitor
  4. * Monitor your servers and websites.
  5. *
  6. * This file is part of PHP Server Monitor.
  7. * PHP Server Monitor is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * PHP Server Monitor is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. * @package phpservermon
  21. * @author Pepijn Over <pep@peplab.net>
  22. * @copyright Copyright (c) 2008-2015 Pepijn Over <pep@peplab.net>
  23. * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
  24. * @version Release: @package_version@
  25. * @link http://www.phpservermonitor.org/
  26. * @since phpservermon 2.1.0
  27. **/
  28. namespace psm\Module\Install\Controller;
  29. use psm\Module\AbstractController;
  30. use psm\Service\Database;
  31. class InstallController extends AbstractController {
  32. /**
  33. * Full path to config file
  34. * @var string $path_config
  35. */
  36. protected $path_config;
  37. /**
  38. * Full path to old config file (2.0)
  39. * @var string $path_config_old
  40. */
  41. protected $path_config_old;
  42. function __construct(Database $db, \Twig_Environment $twig) {
  43. parent::__construct($db, $twig);
  44. $this->setMinUserLevelRequired(PSM_USER_ANONYMOUS);
  45. $this->setCSRFKey('install');
  46. $this->addMenu(false);
  47. $this->path_config = PSM_PATH_SRC . '../config.php';
  48. $this->path_config_old = PSM_PATH_SRC . '../config.inc.php';
  49. $this->setActions(array(
  50. 'index', 'config', 'install'
  51. ), 'index');
  52. $this->twig->addGlobal('subtitle', psm_get_lang('system,', 'install'));
  53. }
  54. /**
  55. * Say hi to our new user
  56. */
  57. protected function executeIndex() {
  58. // build prerequisites
  59. $errors = 0;
  60. $phpv = phpversion();
  61. if(version_compare($phpv, '5.3.7', '<')) {
  62. $errors++;
  63. $this->addMessage('PHP 5.3.7+ is required to run PHP Server Monitor.', 'error');
  64. } else {
  65. $this->addMessage('PHP version: ' . $phpv, 'success');
  66. }
  67. if(!function_exists('curl_init')) {
  68. $this->addMessage('PHP is installed without the cURL module. Please install cURL.', 'warning');
  69. } else {
  70. $this->addMessage('PHP cURL module found', 'success');
  71. }
  72. if(!in_array('mysql', \PDO::getAvailableDrivers())) {
  73. $errors++;
  74. $this->addMessage('The PDO MySQL driver needs to be installed.', 'error');
  75. }
  76. if(!ini_get('date.timezone')) {
  77. $this->addMessage('You should set a timezone in your php.ini file (e.g. \'date.timezone = UTC\'). See <a href="http://www.php.net/manual/en/timezones.php" target="_blank">this page</a> for more info.', 'warning');
  78. }
  79. if($errors > 0) {
  80. $this->addMessage($errors . ' error(s) have been encountered. Please fix them and refresh this page.', 'error');
  81. }
  82. return $this->twig->render('module/install/index.tpl.html', array(
  83. 'messages' => $this->getMessages()
  84. ));
  85. }
  86. /**
  87. * Help the user create a new config file
  88. */
  89. protected function executeConfig() {
  90. $tpl_name = 'module/install/config_new.tpl.html';
  91. $tpl_data = array();
  92. if(!defined('PSM_DB_PREFIX')) {
  93. // first detect "old" config file (2.0)
  94. if(file_exists($this->path_config_old)) {
  95. // oldtimer huh
  96. $this->addMessage('Configuration file for v2.0 found.', 'success');
  97. $this->addMessage(
  98. 'The location of the config file has been changed since v2.0.<br/>' .
  99. 'We will attempt to create a new config file for you.'
  100. , 'warning');
  101. $values = $this->parseConfig20();
  102. } else {
  103. // fresh install
  104. $values = $_POST;
  105. }
  106. $config = array(
  107. 'host' => 'localhost',
  108. 'name' => '',
  109. 'user' => '',
  110. 'pass' => '',
  111. 'prefix' => 'psm_',
  112. );
  113. $changed = false;
  114. foreach($config as $ckey => &$cvalue) {
  115. if(isset($values[$ckey])) {
  116. $changed = true;
  117. $cvalue = $values[$ckey];
  118. }
  119. }
  120. // add config to template data for prefilling the form
  121. $tpl_data = $config;
  122. if($changed) {
  123. // test db connection
  124. $this->db = new \psm\Service\Database(
  125. $config['host'],
  126. $config['user'],
  127. $config['pass'],
  128. $config['name']
  129. );
  130. if($this->db->status()) {
  131. $this->addMessage('Connection to MySQL successful.', 'success');
  132. $config_php = $this->writeConfigFile($config);
  133. if($config_php === true) {
  134. $this->addMessage('Configuration file written successfully.', 'success');
  135. } else {
  136. $this->addMessage('Config file is not writable, we cannot save it for you.', 'error');
  137. $tpl_data['include_config_new_copy'] = true;
  138. $tpl_data['php_config'] = $config_php;
  139. }
  140. } else {
  141. $this->addMessage('Unable to connect to MySQL. Please check your information.', 'error');
  142. }
  143. }
  144. }
  145. if(defined('PSM_DB_PREFIX')) {
  146. if($this->db->status()) {
  147. if($this->isUpgrade()) {
  148. // upgrade
  149. if(version_compare($this->getPreviousVersion(), '3.0.0', '<')) {
  150. // upgrade from before 3.0, does not have passwords yet.. create new user first
  151. $this->addMessage('Your current version does not have an authentication system, but since v3.0 access to the monitor is restricted by user accounts. Please set up a new account to be able to login after the upgrade, and which you can use to change the passwords for your other accounts.', 'info');
  152. $tpl_name = 'module/install/config_new_user.tpl.html';
  153. } else {
  154. $tpl_name = 'module/install/config_upgrade.tpl.html';
  155. $tpl_data['version'] = PSM_VERSION;
  156. }
  157. } else {
  158. // fresh install ahead
  159. $tpl_name = 'module/install/config_new_user.tpl.html';
  160. $tpl_data['username'] = (isset($_POST['username'])) ? $_POST['username'] : '';
  161. $tpl_data['email'] = (isset($_POST['email'])) ? $_POST['email'] : '';
  162. }
  163. } else {
  164. $this->addMessage('Configuration file found, but unable to connect to MySQL. Please check your information.', 'error');
  165. }
  166. }
  167. $tpl_data['messages'] = $this->getMessages();
  168. return $this->twig->render($tpl_name, $tpl_data);
  169. }
  170. /**
  171. * Execute the install and upgrade process to a newer version
  172. */
  173. protected function executeInstall() {
  174. if(!defined('PSM_DB_PREFIX') || !$this->db->status()) {
  175. return $this->executeConfig();
  176. }
  177. $add_user = false;
  178. // check if user submitted username + password in previous step
  179. // this would only be the case for new installs, and install from
  180. // before 3.0
  181. $new_user = array(
  182. 'user_name' => psm_POST('username'),
  183. 'name' => psm_POST('username'),
  184. 'password' => psm_POST('password'),
  185. 'password_repeat' => psm_POST('password_repeat'),
  186. 'email' => psm_POST('email', ''),
  187. 'mobile' => '',
  188. 'level' => PSM_USER_ADMIN,
  189. 'pushover_key' => '',
  190. 'pushover_device' => '',
  191. );
  192. $validator = $this->container->get('util.user.validator');
  193. $logger = array($this, 'addMessage');
  194. $installer = new \psm\Util\Install\Installer($this->db, $logger);
  195. if($this->isUpgrade()) {
  196. $this->addMessage('Upgrade process started.', 'info');
  197. $version_from = $this->getPreviousVersion();
  198. if($version_from === false) {
  199. $this->addMessage('Unable to locate your previous version. Please run a fresh install.', 'error');
  200. } else {
  201. if(version_compare($version_from, PSM_VERSION, '=')) {
  202. $this->addMessage('Your installation is already at the latest version.', 'success');
  203. } elseif(version_compare($version_from, PSM_VERSION, '>')) {
  204. $this->addMessage('This installer does not support downgrading, sorry.', 'error');
  205. } else {
  206. $this->addMessage('Upgrading from ' . $version_from . ' to ' . PSM_VERSION, 'info');
  207. $installer->upgrade($version_from, PSM_VERSION);
  208. }
  209. if(version_compare($version_from, '3.0.0', '<')) {
  210. $add_user = true;
  211. }
  212. }
  213. } else {
  214. // validate the lot
  215. try {
  216. $validator->email($new_user['email']);
  217. $validator->password($new_user['password'], $new_user['password_repeat']);
  218. } catch(\InvalidArgumentException $e) {
  219. $this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error');
  220. return $this->executeConfig();
  221. }
  222. $this->addMessage('Installation process started.', 'success');
  223. $installer->install();
  224. // add user
  225. $add_user = true;
  226. }
  227. if($add_user) {
  228. unset($new_user['password_repeat']);
  229. $user_id = $this->db->save(PSM_DB_PREFIX.'users', $new_user);
  230. if(intval($user_id) > 0) {
  231. $this->getUser()->changePassword($user_id, $new_user['password']);
  232. $this->addMessage('User account has been created successfully.', 'success');
  233. } else {
  234. $this->addMessage('There was an error adding your user account.', 'error');
  235. }
  236. }
  237. return $this->twig->render('module/install/success.tpl.html', array(
  238. 'messages' => $this->getMessages()
  239. ));
  240. }
  241. /**
  242. * Write config file with db variables
  243. * @param array $db_vars prefix,user,pass,name,host
  244. * @return boolean|string TRUE on success, string with config otherwise
  245. */
  246. protected function writeConfigFile($db_vars) {
  247. $config = "<?php".PHP_EOL;
  248. foreach($db_vars as $key => $value) {
  249. $line = "define('PSM_DB_{key}', '{value}');".PHP_EOL;
  250. $line = str_replace(
  251. array('{key}', '{value}'),
  252. array(strtoupper($key), $value),
  253. $line
  254. );
  255. $config .= $line;
  256. }
  257. if(is_writeable($this->path_config)) {
  258. file_put_contents($this->path_config, $config);
  259. return true;
  260. } else {
  261. return $config;
  262. }
  263. }
  264. /**
  265. * Parse the 2.0 config file for prefilling
  266. * @return array
  267. */
  268. protected function parseConfig20() {
  269. $config_old = file_get_contents($this->path_config_old);
  270. $vars = array(
  271. 'prefix' => '',
  272. 'user' => '',
  273. 'pass' => '',
  274. 'name' => '',
  275. 'host' => '',
  276. );
  277. $pattern = "/define\('SM_DB_{key}', '(.*?)'/u";
  278. foreach($vars as $key => $value) {
  279. $pattern_key = str_replace('{key}', strtoupper($key), $pattern);
  280. preg_match($pattern_key, $config_old, $value_matches);
  281. $vars[$key] = (isset($value_matches[1])) ? $value_matches[1] : '';
  282. }
  283. return $vars;
  284. }
  285. /**
  286. * Is it an upgrade or install?
  287. */
  288. protected function isUpgrade() {
  289. if(!$this->db->status()) {
  290. return false;
  291. }
  292. return $this->db->ifTableExists(PSM_DB_PREFIX.'config');
  293. }
  294. /**
  295. * Get the previous version from the config table
  296. * @return boolean|string FALSE on failure, string otherwise
  297. */
  298. protected function getPreviousVersion() {
  299. if(!$this->isUpgrade()) {
  300. return false;
  301. }
  302. $version_conf = $this->db->selectRow(PSM_DB_PREFIX . 'config', array('key' => 'version'), array('value'));
  303. if(empty($version_conf)) {
  304. return false;
  305. } else {
  306. $version_from = $version_conf['value'];
  307. if(strpos($version_from, '.') === false) {
  308. // yeah, my bad.. previous version did not follow proper naming scheme
  309. $version_from = rtrim(chunk_split($version_from, 1, '.'), '.');
  310. }
  311. return $version_from;
  312. }
  313. }
  314. }