PageRenderTime 68ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/phpmyfaq/inc/Installer.php

https://github.com/cyrke/phpMyFAQ
PHP | 838 lines | 623 code | 61 blank | 154 comment | 55 complexity | 2a76940b398103b464745906b1de7d5f MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. * The Installer class installs phpMyFAQ. Classy.
  4. *
  5. * PHP Version 5.3
  6. *
  7. * This Source Code Form is subject to the terms of the Mozilla Public License,
  8. * v. 2.0. If a copy of the MPL was not distributed with this file, You can
  9. * obtain one at http://mozilla.org/MPL/2.0/.
  10. *
  11. * @category phpMyFAQ
  12. * @package Installer
  13. * @author Florian Anderiasch <florian@phpmyfaq.net>
  14. * @copyright 2002-2012 phpMyFAQ Team
  15. * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
  16. * @link http://www.phpmyfaq.de
  17. * @since 2012-08-27
  18. */
  19. if (!defined('IS_VALID_PHPMYFAQ')) {
  20. exit();
  21. }
  22. /**
  23. * Installer
  24. *
  25. * @category phpMyFAQ
  26. * @package Installer
  27. * @author Florian Anderiasch <florian@phpmyfaq.net>
  28. * @copyright 2002-2012 phpMyFAQ Team
  29. * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
  30. * @link http://www.phpmyfaq.de
  31. * @since 2012-08-27
  32. */
  33. class PMF_Installer
  34. {
  35. /**
  36. * PMF_System object
  37. *
  38. * @var PMF_System
  39. */
  40. protected $_system;
  41. /**
  42. * Array with user rights
  43. * @var array
  44. */
  45. protected $_mainRights = array(
  46. //1 => "adduser",
  47. array(
  48. 'name' => 'adduser',
  49. 'description' => 'Right to add user accounts'
  50. ),
  51. //2 => "edituser",
  52. array(
  53. 'name' => 'edituser',
  54. 'description' => 'Right to edit user accounts'
  55. ),
  56. //3 => "deluser",
  57. array(
  58. 'name' => 'deluser',
  59. 'description' => 'Right to delete user accounts'
  60. ),
  61. //4 => "addbt",
  62. array(
  63. 'name' => 'addbt',
  64. 'description' => 'Right to add faq entries'
  65. ),
  66. //5 => "editbt",
  67. array(
  68. 'name' => 'editbt',
  69. 'description' => 'Right to edit faq entries'
  70. ),
  71. //6 => "delbt",
  72. array(
  73. 'name' => 'delbt',
  74. 'description' => 'Right to delete faq entries'
  75. ),
  76. //7 => "viewlog",
  77. array(
  78. 'name' => 'viewlog',
  79. 'description' => 'Right to view logfiles'
  80. ),
  81. //8 => "adminlog",
  82. array(
  83. 'name' => 'adminlog',
  84. 'description' => 'Right to view admin log'
  85. ),
  86. //9 => "delcomment",
  87. array(
  88. 'name' => 'delcomment',
  89. 'description' => 'Right to delete comments'
  90. ),
  91. //10 => "addnews",
  92. array(
  93. 'name' => 'addnews',
  94. 'description' => 'Right to add news'
  95. ),
  96. //11 => "editnews",
  97. array(
  98. 'name' => 'editnews',
  99. 'description' => 'Right to edit news'
  100. ),
  101. //12 => "delnews",
  102. array(
  103. 'name' => 'delnews',
  104. 'description' => 'Right to delete news'
  105. ),
  106. //13 => "addcateg",
  107. array(
  108. 'name' => 'addcateg',
  109. 'description' => 'Right to add categories'
  110. ),
  111. //14 => "editcateg",
  112. array(
  113. 'name' => 'editcateg',
  114. 'description' => 'Right to edit categories'
  115. ),
  116. //15 => "delcateg",
  117. array(
  118. 'name' => 'delcateg',
  119. 'description' => 'Right to delete categories'
  120. ),
  121. //16 => "passwd",
  122. array(
  123. 'name' => 'passwd',
  124. 'description' => 'Right to change passwords'
  125. ),
  126. //17 => "editconfig",
  127. array(
  128. 'name' => 'editconfig',
  129. 'description' => 'Right to edit configuration'
  130. ),
  131. //18 => "addatt", // Duplicate, removed with 2.7.3
  132. //array(
  133. // 'name' => 'addatt',
  134. // 'description' => 'Right to add attachments'
  135. //),
  136. //19 => "backup delatt", // Duplicate, removed with 2.7.3
  137. //array(
  138. // 'name' => 'delatt',
  139. // 'description' => 'Right to delete attachments'
  140. //),
  141. //20 => "backup",
  142. array(
  143. 'name' => 'backup',
  144. 'description' => 'Right to save backups'
  145. ),
  146. //21 => "restore",
  147. array(
  148. 'name' => 'restore',
  149. 'description' => 'Right to load backups'
  150. ),
  151. //22 => "delquestion",
  152. array(
  153. 'name' => 'delquestion',
  154. 'description' => 'Right to delete questions'
  155. ),
  156. //23 => 'addglossary',
  157. array(
  158. 'name' => 'addglossary',
  159. 'description' => 'Right to add glossary entries'
  160. ),
  161. //24 => 'editglossary',
  162. array(
  163. 'name' => 'editglossary',
  164. 'description' => 'Right to edit glossary entries'
  165. ),
  166. //25 => 'delglossary'
  167. array(
  168. 'name' => 'delglossary',
  169. 'description' => 'Right to delete glossary entries'
  170. ),
  171. //26 => 'changebtrevs'
  172. array(
  173. 'name' => 'changebtrevs',
  174. 'description' => 'Right to edit revisions'
  175. ),
  176. //27 => "addgroup",
  177. array(
  178. 'name' => 'addgroup',
  179. 'description' => 'Right to add group accounts'
  180. ),
  181. //28 => "editgroup",
  182. array(
  183. 'name' => 'editgroup',
  184. 'description' => 'Right to edit group accounts'
  185. ),
  186. //29 => "delgroup",
  187. array(
  188. 'name' => 'delgroup',
  189. 'description' => 'Right to delete group accounts'
  190. ),
  191. //30 => "addtranslation",
  192. array(
  193. 'name' => 'addtranslation',
  194. 'description' => 'Right to add translation'
  195. ),
  196. //31 => "edittranslation",
  197. array(
  198. 'name' => 'edittranslation',
  199. 'description' => 'Right to edit translations'
  200. ),
  201. //32 => "deltranslation",
  202. array(
  203. 'name' => 'deltranslation',
  204. 'description' => 'Right to delete translations'
  205. ),
  206. // 33 => 'approverec'
  207. array(
  208. 'name' => 'approverec',
  209. 'description' => 'Right to approve records'
  210. ),
  211. // 34 => 'addattachment'
  212. array(
  213. 'name' => 'addattachment',
  214. 'description' => 'Right to add attachments'
  215. ),
  216. // 35 => 'editattachment'
  217. array(
  218. 'name' => 'editattachment',
  219. 'description' => 'Right to edit attachments'
  220. ),
  221. // 36 => 'delattachment'
  222. array(
  223. 'name' => 'delattachment',
  224. 'description' => 'Right to delete attachments'
  225. ),
  226. // 37 => 'dlattachment'
  227. array(
  228. 'name' => 'dlattachment',
  229. 'description' => 'Right to download attachments'
  230. ),
  231. // 38 => 'dlattachment'
  232. array(
  233. 'name' => 'reports',
  234. 'description' => 'Right to generate reports'
  235. ),
  236. // 39 => 'addfaq'
  237. array(
  238. 'name' => 'addfaq',
  239. 'description' => 'Right to add FAQs in frontend'
  240. ),
  241. // 40 => 'addquestion'
  242. array(
  243. 'name' => 'addquestion',
  244. 'description' => 'Right to add questions in frontend'
  245. ),
  246. // 41 => 'addcomment'
  247. array(
  248. 'name' => 'addcomment',
  249. 'description' => 'Right to add comments in frontend'
  250. ),
  251. // 42 => 'editinstances'
  252. array(
  253. 'name' => 'editinstances',
  254. 'description' => 'Right to edit multi-site instances'
  255. ),
  256. // 43 => 'addinstances'
  257. array(
  258. 'name' => 'addinstances',
  259. 'description' => 'Right to add multi-site instances'
  260. ),
  261. // 44 => 'delinstances'
  262. array(
  263. 'name' => 'delinstances',
  264. 'description' => 'Right to delete multi-site instances'
  265. ),
  266. // 45 => 'export'
  267. array(
  268. 'name' => 'export',
  269. 'description' => 'Right to export the complete FAQ'
  270. ),
  271. );
  272. /**
  273. * Configuration array
  274. *
  275. * @var array
  276. */
  277. protected $_mainConfig = array(
  278. 'main.currentVersion' => null,
  279. 'main.currentApiVersion' => null,
  280. 'main.language' => '__PHPMYFAQ_LANGUAGE__',
  281. 'main.languageDetection' => 'true',
  282. 'main.phpMyFAQToken' => null,
  283. 'main.referenceURL' => '__PHPMYFAQ_REFERENCE_URL__',
  284. 'main.administrationMail' => 'webmaster@example.org',
  285. 'main.contactInformations' => '',
  286. 'main.enableAdminLog' => 'true',
  287. 'main.enableRewriteRules' => 'false',
  288. 'main.enableUserTracking' => 'true',
  289. 'main.metaDescription' => 'phpMyFAQ should be the answer for all questions in life',
  290. 'main.metaKeywords' => '',
  291. 'main.metaPublisher' => '__PHPMYFAQ_PUBLISHER__',
  292. 'main.send2friendText' => '',
  293. 'main.titleFAQ' => 'phpMyFAQ Codename Perdita',
  294. 'main.urlValidateInterval' => '86400',
  295. 'main.enableWysiwygEditor' => 'true',
  296. 'main.templateSet' => 'default',
  297. 'main.optionalMailAddress' => 'false',
  298. 'main.enableGoogleTranslation' => 'false',
  299. 'main.googleTranslationKey' => '',
  300. 'main.dateFormat' => 'Y-m-d H:i',
  301. 'main.maintenanceMode' => 'false',
  302. 'records.numberOfRecordsPerPage' => '10',
  303. 'records.numberOfShownNewsEntries' => '3',
  304. 'records.defaultActivation' => 'false',
  305. 'records.defaultAllowComments' => 'false',
  306. 'records.enableVisibilityQuestions' => 'false',
  307. 'records.numberOfRelatedArticles' => '5',
  308. 'records.orderby' => 'id',
  309. 'records.sortby' => 'DESC',
  310. 'records.orderingPopularFaqs' => 'visits',
  311. 'records.disableAttachments' => 'true',
  312. 'records.maxAttachmentSize' => '100000',
  313. 'records.attachmentsPath' => 'attachments',
  314. 'records.attachmentsStorageType' => '0',
  315. 'records.enableAttachmentEncryption' => 'false',
  316. 'records.defaultAttachmentEncKey' => '',
  317. 'records.enableCloseQuestion' => 'false',
  318. 'records.enableDeleteQuestion' => 'false',
  319. 'records.autosaveActive' => 'false',
  320. 'records.autosaveSecs' => '180',
  321. 'search.useAjaxSearchOnStartpage' => 'false',
  322. 'search.numberSearchTerms' => '10',
  323. 'search.relevance' => 'thema,content,keywords',
  324. 'search.enableRelevance' => 'false',
  325. 'security.permLevel' => 'basic',
  326. 'security.ipCheck' => 'false',
  327. 'security.enableLoginOnly' => 'false',
  328. 'security.ldapSupport' => 'false',
  329. 'security.bannedIPs' => '',
  330. 'security.ssoSupport' => 'false',
  331. 'security.ssoLogoutRedirect' => '',
  332. 'security.useSslForLogins' => 'false',
  333. 'security.useSslOnly' => 'false',
  334. 'security.forcePasswordUpdate' => 'false',
  335. 'spam.checkBannedWords' => 'true',
  336. 'spam.enableCaptchaCode' => null,
  337. 'spam.enableSafeEmail' => 'true',
  338. 'socialnetworks.enableTwitterSupport' => 'false',
  339. 'socialnetworks.twitterConsumerKey' => '',
  340. 'socialnetworks.twitterConsumerSecret' => '',
  341. 'socialnetworks.twitterAccessTokenKey' => '',
  342. 'socialnetworks.twitterAccessTokenSecret' => '',
  343. 'socialnetworks.enableFacebookSupport' => 'false',
  344. 'cache.varnishEnable' => 'false',
  345. 'cache.varnishHost' => '127.0.0.1',
  346. 'cache.varnishPort' => '2000',
  347. 'cache.varnishSecret' => '',
  348. 'cache.varnishTimeout' => '500'
  349. );
  350. /**
  351. * Constructor
  352. *
  353. * @return PMF_Installer
  354. */
  355. public function __construct()
  356. {
  357. $this->_system = new PMF_System();
  358. $dynMainConfig = array(
  359. 'main.currentVersion' => PMF_System::getVersion(),
  360. 'main.currentApiVersion' => PMF_System::getApiVersion(),
  361. 'main.phpMyFAQToken' => md5(uniqid(rand())),
  362. 'spam.enableCaptchaCode' => (extension_loaded('gd') ? 'true' : 'false'),
  363. );
  364. $this->_mainConfig = array_merge($this->_mainConfig, $dynMainConfig);
  365. }
  366. /**
  367. * Check absolutely necessary stuff and die
  368. *
  369. * @return void
  370. */
  371. public function checkBasicStuff()
  372. {
  373. if (!$this->checkMinimumPhpVersion()) {
  374. printf('<p class="alert alert-error">Sorry, but you need PHP %s or later!</p>', PMF_System::VERSION_MINIMUM_PHP);
  375. PMF_System::renderFooter();
  376. }
  377. if (! function_exists('date_default_timezone_set')) {
  378. echo '<p class="alert alert-error">Sorry, but setting a default timezone doesn\'t work in your environment!</p>';
  379. PMF_System::renderFooter();
  380. }
  381. if (! $this->_system->checkDatabase()) {
  382. echo '<p class="alert alert-error">No supported database detected! Please install one of the following' .
  383. ' database systems and enable the corresponding PHP extension in php.ini:</p>';
  384. echo '<ul>';
  385. foreach ($this->_system->getSupportedDatabases() as $database) {
  386. printf(' <li>%s</li>', $database[1]);
  387. }
  388. echo '</ul>';
  389. PMF_System::renderFooter();
  390. }
  391. if (! $this->_system->checkRequiredExtensions()) {
  392. echo '<p class="alert alert-error">The following extensions are missing! Please enable the PHP extension(s) in ' .
  393. 'php.ini.</p>';
  394. echo '<ul>';
  395. foreach ($this->_system->getMissingExtensions() as $extension) {
  396. printf(' <li>ext/%s</li>', $extension);
  397. }
  398. echo '</ul>';
  399. PMF_System::renderFooter();
  400. }
  401. if (! $this->_system->checkphpMyFAQInstallation()) {
  402. echo '<p class="alert alert-error">It seems you\'re already running a version of phpMyFAQ. Please use the ' .
  403. '<a href="update.php">update script</a>.</p>';
  404. PMF_System::renderFooter();
  405. }
  406. }
  407. /**
  408. * Checks for the minimum PHP requirement and if the database credentials file is readable
  409. *
  410. * @return void
  411. */
  412. public function checkPreUpgrade()
  413. {
  414. if (! $this->checkMinimumPhpVersion()) {
  415. printf(
  416. '<p class="alert alert-error">Sorry, but you need PHP %s or later!</p>',
  417. PMF_System::VERSION_MINIMUM_PHP
  418. );
  419. PMF_System::renderFooter();
  420. }
  421. if (! is_readable(PMF_ROOT_DIR . '/inc/data.php') && ! is_readable(PMF_ROOT_DIR . '/config/database.php')) {
  422. echo '<p class="alert alert-error">It seems you never run a version of phpMyFAQ.<br />' .
  423. 'Please use the <a href="setup.php">install script</a>.</p>';
  424. PMF_System::renderFooter();
  425. }
  426. }
  427. /**
  428. * Checks the minimum required PHP version, defined in PMF_System
  429. *
  430. * @return bool
  431. */
  432. public function checkMinimumPhpVersion()
  433. {
  434. if (version_compare(PHP_VERSION, PMF_System::VERSION_MINIMUM_PHP, '<')) {
  435. return false;
  436. }
  437. return true;
  438. }
  439. /**
  440. * Checks if the file permissions are okay
  441. *
  442. * @return void
  443. */
  444. public function checkFilesystemPermissions()
  445. {
  446. $instanceSetup = new PMF_Instance_Setup();
  447. $instanceSetup->setRootDir(PMF_ROOT_DIR);
  448. $dirs = array('/attachments', '/config', '/data', '/images');
  449. $failedDirs = $instanceSetup->checkDirs($dirs);
  450. $numDirs = sizeof($failedDirs);
  451. if (1 <= $numDirs) {
  452. printf(
  453. '<p class="alert alert-error">The following %s could not be created or %s not writable:</p><ul>',
  454. (1 < $numDirs) ? 'directories' : 'directory',
  455. (1 < $numDirs) ? 'are' : 'is'
  456. );
  457. foreach ($failedDirs as $dir) {
  458. echo "<li>$dir</li>\n";
  459. }
  460. printf(
  461. '</ul><p class="alert alert-error">Please create %s manually and/or change access to chmod 755 (or ' .
  462. 'greater if necessary).</p>',
  463. (1 < $numDirs) ? 'them' : 'it'
  464. );
  465. PMF_System::renderFooter();
  466. }
  467. }
  468. /**
  469. * Checks some non critical settings and print some hints
  470. *
  471. * @todo We should return an array of messages
  472. * @return void
  473. */
  474. public function checkNoncriticalSettings()
  475. {
  476. if ((@ini_get('safe_mode') == 'On' || @ini_get('safe_mode') === 1)) {
  477. echo '<p class="alert alert-error">The PHP safe mode is enabled. You may have problems when phpMyFAQ tries to write ' .
  478. ' in some directories.</p>';
  479. }
  480. if (! extension_loaded('gd')) {
  481. echo '<p class="alert alert-error">You don\'t have GD support enabled in your PHP installation. Please enable GD ' .
  482. 'support in your php.ini file otherwise you can\'t use Captchas for spam protection.</p>';
  483. }
  484. if (! function_exists('imagettftext')) {
  485. echo '<p class="alert alert-error">You don\'t have Freetype support enabled in the GD extension of your PHP ' .
  486. 'installation. Please enable Freetype support in GD extension otherwise the Captchas for spam ' .
  487. 'protection will be quite easy to break.</p>';
  488. }
  489. if (! extension_loaded('curl') || ! extension_loaded('openssl')) {
  490. echo '<p class="alert alert-error">You don\'t have cURL and/or OpenSSL support enabled in your PHP installation. ' .
  491. 'Please enable cURL and/or OpenSSL support in your php.ini file otherwise you can\'t use the Twitter ' .
  492. ' support.</p>';
  493. }
  494. }
  495. /**
  496. * Checks if we can store data via sessions. If not, e.g. an user can't
  497. * login into the admin section
  498. *
  499. * @return bool
  500. */
  501. public function checkSessionSettings()
  502. {
  503. return true;
  504. }
  505. /**
  506. * Starts the installation
  507. *
  508. * @param array $DB
  509. */
  510. public function startInstall(Array $DB = null)
  511. {
  512. $query = $uninst = $dbSetup = array();
  513. // Check table prefix
  514. $dbSetup['dbPrefix'] = $sqltblpre = PMF_Filter::filterInput(INPUT_POST, 'sqltblpre', FILTER_SANITIZE_STRING, '');
  515. if ('' !== $dbSetup['dbPrefix']) {
  516. PMF_Db::setTablePrefix($dbSetup['dbPrefix']);
  517. }
  518. // Check database entries
  519. $dbSetup['dbType'] = PMF_Filter::filterInput(INPUT_POST, 'sql_type', FILTER_SANITIZE_STRING);
  520. if (!is_null($dbSetup['dbType'])) {
  521. $dbSetup['dbType'] = trim($dbSetup['dbType']);
  522. if (! file_exists(PMF_ROOT_DIR . '/install/' . $dbSetup['dbType'] . '.sql.php')) {
  523. printf(
  524. '<p class="alert alert-error"><strong>Error:</strong> Invalid server type: %s</p>',
  525. $dbSetup['dbType']
  526. );
  527. PMF_System::renderFooter(true);
  528. }
  529. } else {
  530. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please select a database type.</p>\n";
  531. PMF_System::renderFooter(true);
  532. }
  533. $dbSetup['dbServer'] = PMF_Filter::filterInput(INPUT_POST, 'sql_server', FILTER_SANITIZE_STRING);
  534. if (is_null($dbSetup['dbServer']) && ! PMF_System::isSqlite($dbSetup['dbType'])) {
  535. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a database server.</p>\n";
  536. PMF_System::renderFooter(true);
  537. }
  538. $dbSetup['dbUser'] = PMF_Filter::filterInput(INPUT_POST, 'sql_user', FILTER_SANITIZE_STRING);
  539. if (is_null($dbSetup['dbUser']) && ! PMF_System::isSqlite($dbSetup['dbType'])) {
  540. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a database username.</p>\n";
  541. PMF_System::renderFooter(true);
  542. }
  543. $dbSetup['dbPassword'] = PMF_Filter::filterInput(INPUT_POST, 'sql_passwort', FILTER_UNSAFE_RAW);
  544. if (is_null($dbSetup['dbPassword']) && ! PMF_System::isSqlite($dbSetup['dbType'])) {
  545. // Password can be empty...
  546. $dbSetup['dbPassword'] = '';
  547. }
  548. $dbSetup['dbDatabaseName'] = PMF_Filter::filterInput(INPUT_POST, 'sql_db', FILTER_SANITIZE_STRING);
  549. if (is_null($dbSetup['dbDatabaseName']) && ! PMF_System::isSqlite($dbSetup['dbType'])) {
  550. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a database name.</p>\n";
  551. PMF_System::renderFooter(true);
  552. }
  553. if (PMF_System::isSqlite($dbSetup['dbType'])) {
  554. $dbSetup['dbServer'] = PMF_Filter::filterInput(INPUT_POST, 'sql_sqlitefile', FILTER_SANITIZE_STRING);
  555. if (is_null($dbSetup['dbServer'])) {
  556. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a SQLite database filename.</p>\n";
  557. PMF_System::renderFooter(true);
  558. }
  559. }
  560. // check database connection
  561. require PMF_ROOT_DIR . "/inc/DB/Driver.php";
  562. PMF_Db::setTablePrefix($dbSetup['dbPrefix']);
  563. $db = PMF_Db::factory($dbSetup['dbType']);
  564. $db->connect($dbSetup['dbServer'], $dbSetup['dbUser'], $dbSetup['dbPassword'], $dbSetup['dbDatabaseName']);
  565. if (!$db) {
  566. printf("<p class=\"alert alert-error\"><strong>DB Error:</strong> %s</p>\n", $db->error());
  567. PMF_System::renderFooter(true);
  568. }
  569. $configuration = new PMF_Configuration($db);
  570. // check LDAP if available
  571. $ldapEnabled = PMF_Filter::filterInput(INPUT_POST, 'ldap_enabled', FILTER_SANITIZE_STRING);
  572. if (extension_loaded('ldap') && !is_null($ldapEnabled)) {
  573. $ldapSetup = array();
  574. // check LDAP entries
  575. $ldapSetup['ldapServer'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_server', FILTER_SANITIZE_STRING);
  576. if (is_null($ldapSetup['ldapServer'])) {
  577. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a LDAP server.</p>\n";
  578. PMF_System::renderFooter(true);
  579. }
  580. $ldapSetup['ldapPort'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_port', FILTER_VALIDATE_INT);
  581. if (is_null($ldapSetup['ldapPort'])) {
  582. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a LDAP port.</p>\n";
  583. PMF_System::renderFooter(true);
  584. }
  585. $ldapSetup['ldapBase'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_base', FILTER_SANITIZE_STRING);
  586. if (is_null($ldapSetup['ldapBase'])) {
  587. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a LDAP base search DN.</p>\n";
  588. PMF_System::renderFooter(true);
  589. }
  590. // LDAP User and LDAP password are optional
  591. $ldapSetup['ldapUser'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_user', FILTER_SANITIZE_STRING, '');
  592. $ldapSetup['ldapPassword'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_password', FILTER_SANITIZE_STRING, '');
  593. // check LDAP connection
  594. require PMF_ROOT_DIR . "/inc/Ldap.php";
  595. $ldap = new PMF_Ldap($configuration);
  596. $ldap->connect(
  597. $ldapSetup['ldapServer'],
  598. $ldapSetup['ldapPort'],
  599. $ldapSetup['ldapBase'],
  600. $ldapSetup['ldapUser'],
  601. $ldapSetup['ldapPassword']
  602. );
  603. if (!$ldap) {
  604. echo "<p class=\"alert alert-error\"><strong>LDAP Error:</strong> " . $ldap->error() . "</p>\n";
  605. PMF_System::renderFooter(true);
  606. }
  607. }
  608. // check loginname
  609. $loginname = PMF_Filter::filterInput(INPUT_POST, 'loginname', FILTER_SANITIZE_STRING);
  610. if (is_null($loginname)) {
  611. echo '<p class="alert alert-error"><strong>Error:</strong> Please add a loginname for your account.</p>';
  612. PMF_System::renderFooter(true);
  613. }
  614. // check user entries
  615. $password = PMF_Filter::filterInput(INPUT_POST, 'password', FILTER_SANITIZE_STRING);
  616. if (is_null($password)) {
  617. echo '<p class="alert alert-error"><strong>Error:</strong> Please add a password for the your account.</p>';
  618. PMF_System::renderFooter(true);
  619. }
  620. $password_retyped = PMF_Filter::filterInput(INPUT_POST, 'password_retyped', FILTER_SANITIZE_STRING);
  621. if (is_null($password_retyped)) {
  622. echo '<p class="alert alert-error"><strong>Error:</strong> Please add a retyped password.</p>';
  623. PMF_System::renderFooter(true);
  624. }
  625. if (strlen($password) <= 5 || strlen($password_retyped) <= 5) {
  626. echo '<p class="alert alert-error"><strong>Error:</strong> Your password and retyped password are too short.' .
  627. ' Please set your password and your retyped password with a minimum of 6 characters.</p>';
  628. PMF_System::renderFooter(true);
  629. }
  630. if ($password != $password_retyped) {
  631. echo '<p class="alert alert-error"><strong>Error:</strong> Your password and retyped password are not equal.' .
  632. ' Please check your password and your retyped password.</p>';
  633. PMF_System::renderFooter(true);
  634. }
  635. $language = PMF_Filter::filterInput(INPUT_POST, 'language', FILTER_SANITIZE_STRING, 'en');
  636. $realname = PMF_Filter::filterInput(INPUT_POST, 'realname', FILTER_SANITIZE_STRING, '');
  637. $email = PMF_Filter::filterInput(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL, '');
  638. $permLevel = PMF_Filter::filterInput(INPUT_POST, 'permLevel', FILTER_SANITIZE_STRING, 'basic');
  639. $instanceSetup = new PMF_Instance_Setup();
  640. $instanceSetup->setRootDir(PMF_ROOT_DIR);
  641. // Write the DB variables in database.php
  642. if (! $instanceSetup->createDatabaseFile($dbSetup)) {
  643. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Setup cannot write to ./config/database.php.</p>";
  644. $this->_system->cleanInstallation();
  645. PMF_System::renderFooter(true);
  646. }
  647. // check LDAP if available
  648. if (extension_loaded('ldap') && !is_null($ldapEnabled)) {
  649. if (! $instanceSetup->createLdapFile($ldapSetup)) {
  650. echo "<p class=\"alert alert-error\"><strong>Error:</strong> Setup cannot write to ./config/ldap.php.</p>";
  651. $this->_system->cleanInstallation();
  652. PMF_System::renderFooter(true);
  653. }
  654. }
  655. // connect to the database using config/database.php
  656. require PMF_ROOT_DIR . '/config/database.php';
  657. $db = PMF_Db::factory($dbSetup['dbType']);
  658. $db->connect($DB['server'], $DB['user'], $DB['password'], $DB['db']);
  659. if (!$db) {
  660. echo "<p class=\"alert alert-error\"><strong>DB Error:</strong> ".$db->error()."</p>\n";
  661. $this->_system->cleanInstallation();
  662. PMF_System::renderFooter(true);
  663. }
  664. require PMF_ROOT_DIR . '/install/' . $dbSetup['dbType'] . '.sql.php'; // CREATE TABLES
  665. require PMF_ROOT_DIR . '/install/stopwords.sql.php'; // INSERTs for stopwords
  666. $this->_system->setDatabase($db);
  667. echo '<p>';
  668. // Erase any table before starting creating the required ones
  669. if (! PMF_System::isSqlite($dbSetup['dbType'])) {
  670. $this->_system->dropTables($uninst);
  671. }
  672. // Start creating the required tables
  673. $count = 0;
  674. foreach ($query as $executeQuery) {
  675. $result = @$db->query($executeQuery);
  676. if (!$result) {
  677. echo '<p class="alert alert-error"><strong>Error:</strong> Please install your version of phpMyFAQ once again or send
  678. us a <a href=\"http://www.phpmyfaq.de\" target=\"_blank\">bug report</a>.</p>';
  679. printf('<p class="alert alert-error"><strong>DB error:</strong> %s</p>', $db->error());
  680. printf('<code>%s</code>', htmlentities($executeQuery));
  681. $this->_system->dropTables($uninst);
  682. $this->_system->cleanInstallation();
  683. PMF_System::renderFooter(true);
  684. }
  685. usleep(2500);
  686. $count++;
  687. if (!($count % 10)) {
  688. echo '| ';
  689. }
  690. }
  691. $link = new PMF_Link(null, $configuration);
  692. // add main configuration, add personal settings
  693. $this->_mainConfig['main.metaPublisher'] = $realname;
  694. $this->_mainConfig['main.administrationMail'] = $email;
  695. $this->_mainConfig['main.language'] = $language;
  696. $this->_mainConfig['security.permLevel'] = $permLevel;
  697. foreach ($this->_mainConfig as $name => $value) {
  698. $configuration->add($name, $value);
  699. }
  700. $configuration->update(array('main.referenceURL' => $link->getSystemUri('/install/setup.php')));
  701. $configuration->add('security.salt', md5($configuration->get('main.referenceURL')));
  702. // add admin account and rights
  703. $admin = new PMF_User($configuration);
  704. if (! $admin->createUser($loginname, $password, 1)) {
  705. echo "<p class=\"alert alert-error\"><strong>Fatal installation error:</strong> " .
  706. "Couldn't create the admin user.</p>\n";
  707. $this->_system->cleanInstallation();
  708. PMF_System::renderFooter(true);
  709. }
  710. $admin->setStatus('protected');
  711. $adminData = array(
  712. 'display_name' => $realname,
  713. 'email' => $email
  714. );
  715. $admin->setUserData($adminData);
  716. // add default rights
  717. foreach ($this->_mainRights as $right) {
  718. $admin->perm->grantUserRight(1, $admin->perm->addRight($right));
  719. }
  720. // Add anonymous user account
  721. $instanceSetup->createAnonymousUser($configuration);
  722. // Add master instance
  723. $instanceData = array(
  724. 'url' => $link->getSystemUri($_SERVER['SCRIPT_NAME']),
  725. 'instance' => $link->getSystemRelativeUri('install/setup.php'),
  726. 'comment' => 'phpMyFAQ ' . PMF_System::getVersion()
  727. );
  728. $faqInstance = new PMF_Instance($configuration);
  729. $faqInstance->addInstance($instanceData);
  730. $faqInstanceMaster = new PMF_Instance_Master($configuration);
  731. $faqInstanceMaster->createMaster($faqInstance);
  732. echo '</p>';
  733. }
  734. /**
  735. * Cleanup all files after an installation
  736. *
  737. * @return void
  738. */
  739. public function cleanUpFiles()
  740. {
  741. // Remove 'setup.php' file
  742. if (@unlink(basename($_SERVER['SCRIPT_NAME']))) {
  743. echo "<p class=\"alert alert-success\">The file <em>./install/setup.php</em> was deleted automatically.</p>\n";
  744. } else {
  745. echo "<p class=\"alert alert-error\">Please delete the file <em>./install/setup.php</em> manually.</p>\n";
  746. }
  747. // Remove 'update.php' file
  748. if (@unlink(dirname($_SERVER['PATH_TRANSLATED']) . '/update.php')) {
  749. echo "<p class=\"alert alert-success\">The file <em>./install/update.php</em> was deleted automatically.</p>\n";
  750. } else {
  751. echo "<p class=\"alert alert-error\">Please delete the file <em>./install/update.php</em> manually.</p>\n";
  752. }
  753. }
  754. /**
  755. * Echos the questionnaire data
  756. *
  757. * @return void
  758. */
  759. public function printDataList()
  760. {
  761. $q = new PMF_Questionnaire_Data($this->_mainConfig);
  762. $options = $q->get();
  763. echo '<dl>' . PHP_EOL;
  764. array_walk($options, 'data_printer');
  765. printf(
  766. '</dl><input type="hidden" name="systemdata" value="%s" />',
  767. PMF_String::htmlspecialchars(serialize($q->get()), ENT_QUOTES)
  768. );
  769. }
  770. }