index.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <?php
  2. /**
  3. * Bibliotheca
  4. *
  5. * Copyright 2018-2024 Johannes Keßler
  6. *
  7. * This program 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. * This program 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 this program. If not, see http://www.gnu.org/licenses/gpl-3.0.
  19. */
  20. /**
  21. * A plain and simple setup for bibliotheca
  22. * It creates the config file based on the .default file.
  23. * It creates the default database tables.
  24. * It self deletes after a setup is complete to reduce some security risks
  25. */
  26. mb_http_output('UTF-8');
  27. mb_internal_encoding('UTF-8');
  28. error_reporting(-1); // E_ALL & E_STRICT
  29. ini_set('display_errors',true);
  30. date_default_timezone_set('Europe/Berlin');
  31. # check request
  32. $_urlToParse = filter_var($_SERVER['QUERY_STRING'],FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
  33. if(!empty($_urlToParse)) {
  34. if(preg_match('/[\p{C}\p{M}\p{Sc}\p{Sk}\p{So}\p{Zl}\p{Zp}]/u',$_urlToParse) === 1) {
  35. die('Malformed request. Make sure you know what you are doing.');
  36. }
  37. }
  38. $TemplateData = array();
  39. if(!is_dir('../config') || !is_writeable('../config')) {
  40. die('Missing correct write permissions for ../config dir');
  41. }
  42. if(!is_dir('../storage') || !is_writeable('../storage')) {
  43. die('Missing correct write permissions for ../storage dir');
  44. }
  45. if(!is_dir('../systemout') || !is_writeable('../systemout')) {
  46. die('Missing correct write permissions for ../systemout dir');
  47. }
  48. if(!is_writeable(getcwd())) {
  49. die('Missing correct write/delete permissions for the setup folder');
  50. }
  51. $configStep = 'ready';
  52. $configFile = '../config/config.php';
  53. $configFileSkeleton = '../config/config.php.default';
  54. $configBrainz = '../config/config-musicbrainz.php';
  55. $configImdb = '../config/config-imdbweb.php';
  56. if(!file_exists($configFile)) {
  57. if(file_exists($configFileSkeleton) && is_readable($configFileSkeleton)) {
  58. $configStep = 'config';
  59. }
  60. else {
  61. die('Missing needed skeleton config files. Make sure all the files are unpacked correctly.');
  62. }
  63. }
  64. if(file_exists($configFile)) {
  65. $configStep = 'database';
  66. }
  67. if(isset($_GET['done'])) {
  68. $configStep = 'ready';
  69. }
  70. switch($configStep) {
  71. case 'config':
  72. $TemplateData['headline'] = '1. Main config file';
  73. $TemplateData['body'] = 'More special options can be directly edited in the config files themself. Only the basics are covered here.';
  74. $TemplateData['footer'] = 'Next - default database tables';
  75. $TemplateData['result'] = array();
  76. $data = array(
  77. 'timezone' => 'Europe/Berlin',
  78. 'dbhost' => '127.0.01',
  79. 'dbuser' => 'user',
  80. 'dbprefix' => 'bib',
  81. 'dbname' => '',
  82. 'dbpassword' => '',
  83. 'pathabsolute' => ''
  84. );
  85. if(isset($_POST['submitForm'])) {
  86. $fCheck = false;
  87. foreach ($data as $k=>$v) {
  88. if(isset($_POST[$k])) {
  89. $_t = trim($_POST[$k]);
  90. if(!empty($_t)) {
  91. $data[$k] = $_t;
  92. $fCheck = true;
  93. }
  94. else {
  95. $fCheck = false;
  96. break;
  97. }
  98. }
  99. else {
  100. $fCheck = false;
  101. break;
  102. }
  103. }
  104. if(!empty($fCheck)) {
  105. $configFileSkeletonString = file_get_contents($configFileSkeleton);
  106. $configFileString = str_replace('~timezone~',$data['timezone'],$configFileSkeletonString);
  107. $configFileString = str_replace('~dbhost~',$data['dbhost'],$configFileString);
  108. $configFileString = str_replace('~dbuser~',$data['dbuser'],$configFileString);
  109. $configFileString = str_replace('~dbprefix~',$data['dbprefix'],$configFileString);
  110. $configFileString = str_replace('~dbname~',$data['dbname'],$configFileString);
  111. $configFileString = str_replace('~dbpassword~',$data['dbpassword'],$configFileString);
  112. $configFileString = str_replace('~pathabsolute~',$data['pathabsolute'],$configFileString);
  113. if(file_put_contents($configFile, $configFileString)) {
  114. copy($configBrainz.'.default', $configBrainz);
  115. copy($configImdb.'.default', $configImdb);
  116. header('Location: index.php');
  117. exit();
  118. }
  119. else {
  120. $TemplateData['result']['status'] = 'ERROR';
  121. $TemplateData['result']['message'] = 'Config file could not be written. Please check your permission';
  122. }
  123. }
  124. else {
  125. $TemplateData['result']['status'] = 'ERROR';
  126. $TemplateData['result']['message'] = 'Please provide input for all the fields';
  127. }
  128. }
  129. $TemplateData['bodyForm'] = stepConfigForm($data);
  130. break;
  131. case 'database':
  132. $TemplateData['headline'] = '2. Database';
  133. $TemplateData['body'] = 'Check and setup of default tables';
  134. $TemplateData['bodyForm'] = '';
  135. $TemplateData['footer'] = 'Next - Additional tools';
  136. $TemplateData['result'] = array();
  137. if(isset($_POST['submitForm'])) {
  138. if(isset($_POST['resetConfig']) && !empty($_POST['resetConfig'])) {
  139. unlink($configFile);
  140. header('Location: index.php');
  141. }
  142. }
  143. require_once $configFile;
  144. $DB = new mysqli(DB_HOST, DB_USERNAME,DB_PASSWORD, DB_NAME);
  145. $driver = new mysqli_driver();
  146. $driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;
  147. $_conCheck = false;
  148. if ($DB->connect_errno) {
  149. $TemplateData['result']['status'] = 'ERROR';
  150. $TemplateData['result']['message'] = 'Can not connect to database: '.$DB->connect_error;
  151. $TemplateData['bodyForm'] = stepDBRest();
  152. }
  153. else {
  154. $_conCheck = true;
  155. $DB->set_charset("utf8mb4");
  156. $DB->query("SET collation_connection = 'utf8mb4_unicode_ci'");
  157. }
  158. if(!empty($_conCheck)) {
  159. try {
  160. $query = $DB->query("SELECT * FROM information_schema.tables WHERE table_schema = '".DB_NAME."' AND table_name = '".DB_PREFIX."_sys_fields' LIMIT 1");
  161. if($query !== false && $query->num_rows < 1) {
  162. $TemplateData['bodyForm'] = stepDBCreateTables();
  163. }
  164. else {
  165. $TemplateData['result']['status'] = 'ERROR';
  166. $TemplateData['result']['message'] = 'Existing DB Tables found! Setup already complete';
  167. clearSetup();
  168. }
  169. }
  170. catch (Exception $e) {
  171. $TemplateData['result']['status'] = 'ERROR';
  172. $TemplateData['result']['message'] = 'Can not run query: '.$e->getMessage();
  173. }
  174. }
  175. if(isset($_POST['submitForm'])) {
  176. if(isset($_POST['createTables']) && !empty($_POST['createTables'])) {
  177. $sqlSkeleton = file_get_contents('./bibliotheca.sql.default');
  178. file_put_contents('./bibliotheca.sql', str_replace('#REPLACEME#',DB_PREFIX,$sqlSkeleton));
  179. try {
  180. $sqlScript = file('./bibliotheca.sql');
  181. $queryStr = '';
  182. foreach ($sqlScript as $line) {
  183. $startWith = substr(trim($line), 0 ,2);
  184. $endWith = substr(trim($line), -1 ,1);
  185. if (empty($line) || $startWith == '--' || $startWith == '/*' || $startWith == '//') {
  186. continue;
  187. }
  188. $queryStr .= $line;
  189. if ($endWith == ';') {
  190. $DB->query($queryStr);
  191. $queryStr = '';
  192. }
  193. }
  194. header("Location: index.php?done=1");
  195. }
  196. catch (Exception $e) {
  197. $TemplateData['result']['status'] = 'ERROR';
  198. $TemplateData['result']['message'] = 'Can not create needed tables: '.$e->getMessage();
  199. $TemplateData['body'] = 'Please check your DB Settings, files and start over. To restart the setup remove all non .default config files and upload the /setup folder again.';
  200. }
  201. }
  202. }
  203. break;
  204. case 'ready':
  205. default:
  206. $TemplateData['headline'] = 'Complete';
  207. $TemplateData['body'] = 'All done. This file is now gone. To restart the setup remove all non .default config files and upload the /setup folder gain.';
  208. $TemplateData['bodyForm'] = '';
  209. $TemplateData['footer'] = 'cya';
  210. $TemplateData['result'] = array();
  211. clearSetup();
  212. }
  213. header('Content-type: text/html; charset=UTF-8');
  214. ?>
  215. <!DOCTYPE html>
  216. <html>
  217. <head>
  218. <meta charset="UTF-8" />
  219. <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  220. <meta name="author" content="https://www.bananas-playground.net/projekt/bibliotheca/" />
  221. <title>Setup - Bibliotheca</title>
  222. </head>
  223. <body>
  224. <header style="border-bottom: 1px solid gray;">
  225. <h1><?php echo $TemplateData['headline']; ?></h1>
  226. <?php if(!empty($TemplateData['result'])) { ?>
  227. <p>
  228. Result: <?php echo $TemplateData['result']['status']; ?><br />
  229. <?php echo $TemplateData['result']['message']; ?>
  230. </p>
  231. <?php } ?>
  232. </header>
  233. <main>
  234. <p><?php echo $TemplateData['body']; ?></p>
  235. <form method="post" action="">
  236. <?php echo $TemplateData['bodyForm']; ?>
  237. <p><button type="submit" name="submitForm">Save</button></p>
  238. </form>
  239. </main>
  240. <footer style="border-top: 1px solid gray;">
  241. <p><?php echo $TemplateData['footer']; ?></p>
  242. <p>&copy; 2018 - <?php echo date('Y'); ?> <a href="https://www.bananas-playground.net/projekt/bibliotheca/" target=_blank>Bibliotheca</a></p>
  243. </footer>
  244. </body>
  245. </html>
  246. <?php
  247. /**
  248. * all the "methods" for the steps.
  249. * KISS
  250. */
  251. /**
  252. * Step config
  253. *
  254. * @param array $data
  255. * @return string
  256. */
  257. function stepConfigForm(array $data): string {
  258. $timeZones = DateTimeZone::listIdentifiers(DateTimeZone::ALL);
  259. $timeZoneOptions = '';
  260. foreach ($timeZones as $tz) {
  261. $selected = '';
  262. if($tz == $data['timezone']) {
  263. $selected = 'selected="selected"';
  264. }
  265. $timeZoneOptions .= "<option ".$selected." value='".$tz."'>".$tz."</option>";
  266. }
  267. $absPath = getcwd();
  268. $absPath = str_replace("setup", "", $absPath);
  269. return <<<RET
  270. <p>
  271. Select your timezone<br />
  272. <select name="timezone">
  273. {$timeZoneOptions}
  274. </select>
  275. </p>
  276. <p>
  277. The absolute path to this installation on your webspace. Current <b>{$absPath}</b> should be the right one.<br />
  278. Make sure there is a / at the end<br />
  279. <input type="text" name="pathabsolute" value="{$data['pathabsolute']}" size="50">
  280. </p>
  281. <p>
  282. Database Hostname<br />
  283. <input type="text" name="dbhost" value="{$data['dbhost']}">
  284. </p>
  285. <p>
  286. Database User<br />
  287. <input type="text" name="dbuser" value="{$data['dbuser']}">
  288. </p>
  289. <p>
  290. Database Password for the given user<br />
  291. <input type="password" name="dbpassword" value="">
  292. </p>
  293. <p>
  294. Database name<br />
  295. <input type="text" name="dbname" value="{$data['dbname']}">
  296. </p>
  297. <p>
  298. Database table prefix. Default is <b>bib</b>. A _ is added automatically.<br />
  299. <input type="text" name="dbprefix" value="{$data['dbprefix']}">
  300. </p>
  301. RET;
  302. }
  303. /**
  304. * Database step
  305. *
  306. * @return string
  307. */
  308. function stepDBRest(): string {
  309. return <<<RET
  310. <p>
  311. Reset the config file to input the correct DB values:
  312. <input type="checkbox" name="resetConfig" value="1" />
  313. </p>
  314. RET;
  315. }
  316. /**
  317. * database step
  318. *
  319. * @return string
  320. */
  321. function stepDBCreateTables(): string {
  322. return <<<RET
  323. <p>
  324. Warning: Existing data can be lost if the config is wrong!<br />
  325. Create tables: <input type="checkbox" name="createTables" value="1" />
  326. </p>
  327. RET;
  328. }
  329. function clearSetup(): void {
  330. array_map('unlink', glob("../setup/*"));
  331. rmdir('../setup');
  332. }