PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/typolight/install.php

https://github.com/alaittin/testing_tv
PHP | 1041 lines | 689 code | 184 blank | 168 comment | 115 complexity | c07045eb891c345b579883a5c2a719c3 MD5 | raw file
  1. <?php
  2. /**
  3. * TYPOlight Open Source CMS
  4. * Copyright (C) 2005-2010 Leo Feyer
  5. *
  6. * This program is free software: you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation, either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this program. If not, please visit the Free
  18. * Software Foundation website at <http://www.gnu.org/licenses/>.
  19. *
  20. * PHP version 5
  21. * @copyright Leo Feyer 2005-2010
  22. * @author Leo Feyer <http://www.typolight.org>
  23. * @package Backend
  24. * @license LGPL
  25. * @filesource
  26. */
  27. /**
  28. * Initialize the system
  29. */
  30. define('TL_MODE', 'BE');
  31. require_once('../system/initialize.php');
  32. /**
  33. * Show error messages
  34. */
  35. @ini_set('display_errors', 1);
  36. @error_reporting(1);
  37. /**
  38. * Class InstallTool
  39. *
  40. * Back end install tool.
  41. * @copyright Leo Feyer 2005-2010
  42. * @author Leo Feyer <http://www.typolight.org>
  43. * @package Controller
  44. */
  45. class InstallTool extends Controller
  46. {
  47. /**
  48. * Initialize the controller
  49. */
  50. public function __construct()
  51. {
  52. $this->import('String');
  53. parent::__construct();
  54. $GLOBALS['TL_CONFIG']['showHelp'] = false;
  55. $GLOBALS['TL_CONFIG']['displayErrors'] = true;
  56. $this->loadLanguageFile('default');
  57. $this->loadLanguageFile('tl_install');
  58. }
  59. /**
  60. * Run controller and parse the login template
  61. */
  62. public function run()
  63. {
  64. $this->Template = new BackendTemplate('be_install');
  65. /**
  66. * Lock the tool if there are too many login attempts
  67. */
  68. if ($GLOBALS['TL_CONFIG']['installCount'] >= 300)
  69. {
  70. $this->Template->locked = true;
  71. $this->outputAndExit();
  72. }
  73. /**
  74. * Check whether the local configuration file is writeable
  75. */
  76. if ($this->Input->post('FORM_SUBMIT') == 'tl_ftp')
  77. {
  78. $GLOBALS['TL_CONFIG']['useFTP'] = true;
  79. $GLOBALS['TL_CONFIG']['ftpHost'] = $this->Input->post('host');
  80. $GLOBALS['TL_CONFIG']['ftpPath'] = $this->Input->post('path');
  81. $GLOBALS['TL_CONFIG']['ftpUser'] = $this->Input->post('username', true);
  82. $GLOBALS['TL_CONFIG']['ftpPass'] = $this->Input->post('password', true);
  83. // Add trailing slash
  84. if ($GLOBALS['TL_CONFIG']['ftpPath'] != '' && substr($GLOBALS['TL_CONFIG']['ftpPath'], -1) != '/')
  85. {
  86. $GLOBALS['TL_CONFIG']['ftpPath'] .= '/';
  87. }
  88. // Try to connect and locate TYPOlight directory
  89. if (($resFtp = @ftp_connect($GLOBALS['TL_CONFIG']['ftpHost'])) == false)
  90. {
  91. $this->Template->ftpHostError = true;
  92. $this->outputAndExit();
  93. }
  94. elseif (!@ftp_login($resFtp, $GLOBALS['TL_CONFIG']['ftpUser'], $GLOBALS['TL_CONFIG']['ftpPass']))
  95. {
  96. $this->Template->ftpUserError = true;
  97. $this->outputAndExit();
  98. }
  99. elseif (ftp_size($resFtp, $GLOBALS['TL_CONFIG']['ftpPath'] . 'system/typolight.css') == -1)
  100. {
  101. $this->Template->ftpPathError = true;
  102. $this->outputAndExit();
  103. }
  104. // Update the local configuration file
  105. else
  106. {
  107. $this->Config->update("\$GLOBALS['TL_CONFIG']['useFTP']", true);
  108. $this->Config->update("\$GLOBALS['TL_CONFIG']['ftpHost']", $GLOBALS['TL_CONFIG']['ftpHost']);
  109. $this->Config->update("\$GLOBALS['TL_CONFIG']['ftpPath']", $GLOBALS['TL_CONFIG']['ftpPath']);
  110. $this->Config->update("\$GLOBALS['TL_CONFIG']['ftpUser']", $GLOBALS['TL_CONFIG']['ftpUser']);
  111. $this->Config->update("\$GLOBALS['TL_CONFIG']['ftpPass']", $GLOBALS['TL_CONFIG']['ftpPass']);
  112. $this->reload();
  113. }
  114. }
  115. // Import files object AFTER storing the FTP settings
  116. $this->import('Files');
  117. if (!$this->Files->is_writeable('system/config/localconfig.php'))
  118. {
  119. $this->outputAndExit();
  120. }
  121. $this->Template->lcfWriteable = true;
  122. /**
  123. * Show license
  124. */
  125. if ($this->Input->post('FORM_SUBMIT') == 'tl_license')
  126. {
  127. $this->Config->update("\$GLOBALS['TL_CONFIG']['licenseAccepted']", true);
  128. $this->reload();
  129. }
  130. if (!$GLOBALS['TL_CONFIG']['licenseAccepted'])
  131. {
  132. $this->Template->license = true;
  133. $this->outputAndExit();
  134. }
  135. /**
  136. * Check the websitePath
  137. */
  138. if (!preg_match('/^' . preg_quote(TL_PATH, '/') . '\/typolight\/' . preg_quote(basename(__FILE__), '/') . '/', $this->Environment->requestUri) && !is_null($GLOBALS['TL_CONFIG']['websitePath']))
  139. {
  140. $this->Config->delete("\$GLOBALS['TL_CONFIG']['websitePath']");
  141. $this->reload();
  142. }
  143. /**
  144. * Authenticate user
  145. */
  146. if ($this->Input->post('FORM_SUBMIT') == 'tl_login')
  147. {
  148. $_SESSION['TL_INSTALL_AUTH'] = '';
  149. $_SESSION['TL_INSTALL_EXPIRE'] = 0;
  150. list($strPassword, $strSalt) = explode(':', $GLOBALS['TL_CONFIG']['installPassword']);
  151. // Password is correct but not yet salted
  152. if (!strlen($strSalt) && $strPassword == sha1($this->Input->post('password')))
  153. {
  154. $strSalt = substr(md5(uniqid('', true)), 0, 23);
  155. $strPassword = sha1($strSalt . $this->Input->post('password'));
  156. $this->Config->update("\$GLOBALS['TL_CONFIG']['installPassword']", $strPassword . ':' . $strSalt);
  157. }
  158. // Set cookie
  159. if (strlen($strSalt) && $strPassword == sha1($strSalt . $this->Input->post('password')))
  160. {
  161. $_SESSION['TL_INSTALL_EXPIRE'] = (time() + 300);
  162. $_SESSION['TL_INSTALL_AUTH'] = md5(uniqid('', true) . (!$GLOBALS['TL_CONFIG']['disableIpCheck'] ? $this->Environment->ip : '') . session_id());
  163. $this->setCookie('TL_INSTALL_AUTH', $_SESSION['TL_INSTALL_AUTH'], $_SESSION['TL_INSTALL_EXPIRE'], $GLOBALS['TL_CONFIG']['websitePath']);
  164. $this->Config->update("\$GLOBALS['TL_CONFIG']['installCount']", 0);
  165. $this->reload();
  166. }
  167. // Increase count
  168. $this->Config->update("\$GLOBALS['TL_CONFIG']['installCount']", $GLOBALS['TL_CONFIG']['installCount'] + 1);
  169. $this->Template->passwordError = $GLOBALS['TL_LANG']['ERR']['invalidPass'];
  170. }
  171. // Check cookie
  172. if (!$this->Input->cookie('TL_INSTALL_AUTH') || $_SESSION['TL_INSTALL_AUTH'] == '' || $this->Input->cookie('TL_INSTALL_AUTH') != $_SESSION['TL_INSTALL_AUTH'] || $_SESSION['TL_INSTALL_EXPIRE'] < time())
  173. {
  174. $this->Template->login = true;
  175. $this->outputAndExit();
  176. }
  177. // Renew cookie
  178. else
  179. {
  180. $_SESSION['TL_INSTALL_EXPIRE'] = (time() + 300);
  181. $_SESSION['TL_INSTALL_AUTH'] = md5(uniqid('', true) . (!$GLOBALS['TL_CONFIG']['disableIpCheck'] ? $this->Environment->ip : '') . session_id());
  182. $this->setCookie('TL_INSTALL_AUTH', $_SESSION['TL_INSTALL_AUTH'], $_SESSION['TL_INSTALL_EXPIRE'], $GLOBALS['TL_CONFIG']['websitePath']);
  183. }
  184. /**
  185. * Set install script password
  186. */
  187. if ($this->Input->post('FORM_SUBMIT') == 'tl_install')
  188. {
  189. $strPassword = $this->Input->post('password', true);
  190. // Do not allow special characters
  191. if (preg_match('/[#\(\)\/<=>]/', $strPassword))
  192. {
  193. $this->Template->passwordError = $GLOBALS['TL_LANG']['ERR']['extnd'];
  194. }
  195. // Passwords do not match
  196. elseif ($strPassword != $this->Input->post('confirm_password', true))
  197. {
  198. $this->Template->passwordError = $GLOBALS['TL_LANG']['ERR']['passwordMatch'];
  199. }
  200. // Password too short
  201. elseif (utf8_strlen($strPassword) < $GLOBALS['TL_CONFIG']['minPasswordLength'])
  202. {
  203. $this->Template->passwordError = sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], $GLOBALS['TL_CONFIG']['minPasswordLength']);
  204. }
  205. // Save password
  206. else
  207. {
  208. $strSalt = substr(md5(uniqid('', true)), 0, 23);
  209. $strPassword = sha1($strSalt . $strPassword);
  210. $this->Config->update("\$GLOBALS['TL_CONFIG']['installPassword']", $strPassword . ':' . $strSalt);
  211. $this->reload();
  212. }
  213. }
  214. /**
  215. * Password must not be "typolight"
  216. */
  217. list($strPassword, $strSalt) = explode(':', $GLOBALS['TL_CONFIG']['installPassword']);
  218. if ($strPassword == sha1($strSalt . 'typolight'))
  219. {
  220. $this->Template->setPassword = true;
  221. $this->outputAndExit();
  222. }
  223. /**
  224. * Save encryption key
  225. */
  226. if ($this->Input->post('FORM_SUBMIT') == 'tl_encryption')
  227. {
  228. $this->Config->update("\$GLOBALS['TL_CONFIG']['encryptionKey']", (($this->Input->post('key')) ? $this->Input->post('key') : md5(uniqid('', true))));
  229. $this->reload();
  230. }
  231. $this->Template->encryptionKey = $GLOBALS['TL_CONFIG']['encryptionKey'];
  232. if (!strlen($GLOBALS['TL_CONFIG']['encryptionKey']))
  233. {
  234. $this->Template->encryption = true;
  235. $this->outputAndExit();
  236. }
  237. if (utf8_strlen($GLOBALS['TL_CONFIG']['encryptionKey']) < 12)
  238. {
  239. $this->Template->encryptionLength = true;
  240. $this->outputAndExit();
  241. }
  242. /**
  243. * Database
  244. */
  245. $strDrivers = '';
  246. $arrDrivers = array();
  247. if (function_exists('mysql_connect'))
  248. {
  249. $arrDrivers[] = 'MySQL';
  250. }
  251. if (class_exists('mysqli', false))
  252. {
  253. $arrDrivers[] = 'MySQLi';
  254. }
  255. if (function_exists('oci_connect'))
  256. {
  257. $arrDrivers[] = 'Oracle';
  258. }
  259. if (function_exists('mssql_connect'))
  260. {
  261. $arrDrivers[] = 'MSSQL';
  262. }
  263. if (function_exists('pg_connect'))
  264. {
  265. $arrDrivers[] = 'PostgreSQL';
  266. }
  267. if (function_exists('sybase_connect'))
  268. {
  269. $arrDrivers[] = 'Sybase';
  270. }
  271. foreach ($arrDrivers as $strDriver)
  272. {
  273. $strDrivers .= sprintf('<option value="%s"%s>%s</option>',
  274. $strDriver,
  275. (($strDriver == $GLOBALS['TL_CONFIG']['dbDriver']) ? ' selected="selected"' : ''),
  276. $strDriver);
  277. }
  278. $this->Template->drivers = $strDrivers;
  279. $this->Template->driver = $GLOBALS['TL_CONFIG']['dbDriver'];
  280. $this->Template->host = $GLOBALS['TL_CONFIG']['dbHost'];
  281. $this->Template->user = $GLOBALS['TL_CONFIG']['dbUser'];
  282. $this->Template->pass = $GLOBALS['TL_CONFIG']['dbPass'];
  283. $this->Template->port = $GLOBALS['TL_CONFIG']['dbPort'];
  284. $this->Template->pconnect = $GLOBALS['TL_CONFIG']['dbPconnect'];
  285. $this->Template->dbcharset = $GLOBALS['TL_CONFIG']['dbCharset'];
  286. $this->Template->database = $GLOBALS['TL_CONFIG']['dbDatabase'];
  287. /**
  288. * Store database connection parameters
  289. */
  290. if ($this->Input->post('FORM_SUBMIT') == 'tl_database_login')
  291. {
  292. foreach (preg_grep('/^db/', array_keys($_POST)) as $strKey)
  293. {
  294. $this->Config->update("\$GLOBALS['TL_CONFIG']['$strKey']", $this->Input->post($strKey, true));
  295. }
  296. $this->reload();
  297. }
  298. try
  299. {
  300. $this->import('Database');
  301. $this->Database->listTables();
  302. $this->Template->dbConnection = true;
  303. }
  304. catch (Exception $e)
  305. {
  306. $this->Template->dbConnection = false;
  307. $this->Template->dbError = $e->getMessage();
  308. $this->outputAndExit();
  309. }
  310. /**
  311. * Version 2.8 update
  312. */
  313. if ($this->Database->tableExists('tl_layout') && !$this->Database->fieldExists('script', 'tl_layout'))
  314. {
  315. if ($this->Input->post('FORM_SUBMIT') == 'tl_28update')
  316. {
  317. // Database changes
  318. $this->Database->execute("ALTER TABLE `tl_layout` ADD `script` text NULL");
  319. $this->Database->execute("ALTER TABLE `tl_member` ADD `dateAdded` int(10) unsigned NOT NULL default '0'");
  320. $this->Database->execute("ALTER TABLE `tl_member` ADD `currentLogin` int(10) unsigned NOT NULL default '0'");
  321. $this->Database->execute("ALTER TABLE `tl_member` ADD `lastLogin` int(10) unsigned NOT NULL default '0'");
  322. $this->Database->execute("ALTER TABLE `tl_user` ADD `dateAdded` int(10) unsigned NOT NULL default '0'");
  323. $this->Database->execute("ALTER TABLE `tl_user` ADD `currentLogin` int(10) unsigned NOT NULL default '0'");
  324. $this->Database->execute("ALTER TABLE `tl_user` ADD `lastLogin` int(10) unsigned NOT NULL default '0'");
  325. $this->Database->execute("ALTER TABLE `tl_comments` ADD `source` varchar(32) NOT NULL default ''");
  326. $this->Database->execute("ALTER TABLE `tl_comments` ADD KEY `source` (`source`)");
  327. $this->Database->execute("ALTER TABLE `tl_layout` CHANGE `mootools` `mootools` text NULL");
  328. $this->Database->execute("ALTER TABLE `tl_comments` CHANGE `pid` `parent` int(10) unsigned NOT NULL default '0'");
  329. $this->Database->execute("UPDATE tl_member SET dateAdded=tstamp, currentLogin=tstamp");
  330. $this->Database->execute("UPDATE tl_user SET dateAdded=tstamp, currentLogin=tstamp");
  331. $this->Database->execute("UPDATE tl_layout SET mootools='moo_accordion' WHERE mootools='moo_default'");
  332. $this->Database->execute("UPDATE tl_comments SET source='tl_content'");
  333. $this->Database->execute("UPDATE tl_module SET cal_format='next_365', type='eventlist' WHERE type='upcoming_events'");
  334. // Get all front end groups
  335. $objGroups = $this->Database->execute("SELECT id FROM tl_member_group");
  336. $strGroups = serialize($objGroups->fetchEach('id'));
  337. // Update protected elements
  338. $this->Database->prepare("UPDATE tl_page SET groups=? WHERE protected=1 AND groups=''")->execute($strGroups);
  339. $this->Database->prepare("UPDATE tl_content SET groups=? WHERE protected=1 AND groups=''")->execute($strGroups);
  340. $this->Database->prepare("UPDATE tl_module SET groups=? WHERE protected=1 AND groups=''")->execute($strGroups);
  341. // Update layouts
  342. $objLayout = $this->Database->execute("SELECT id, mootools FROM tl_layout");
  343. while ($objLayout->next())
  344. {
  345. $mootools = array('moo_mediabox');
  346. if ($objLayout->mootools != '')
  347. {
  348. $mootools[] = $objLayout->mootools;
  349. }
  350. $this->Database->prepare("UPDATE tl_layout SET mootools=? WHERE id=?")
  351. ->execute(serialize($mootools), $objLayout->id);
  352. }
  353. // Update event reader
  354. if (!file_exists(TL_ROOT . '/templates/event_default.tpl'))
  355. {
  356. $this->Database->execute("UPDATE tl_module SET cal_template='event_full' WHERE cal_template='event_default'");
  357. }
  358. // News comments
  359. $objComment = $this->Database->execute("SELECT * FROM tl_news_comments");
  360. while ($objComment->next())
  361. {
  362. $arrSet = $objComment->row();
  363. $arrSet['source'] = 'tl_news';
  364. $arrSet['parent'] = $arrSet['pid'];
  365. unset($arrSet['id']);
  366. unset($arrSet['pid']);
  367. $this->Database->prepare("INSERT INTO tl_comments %s")->set($arrSet)->execute();
  368. }
  369. // Delete system/modules/news/Comments.php
  370. $this->import('Files');
  371. $this->Files->delete('system/modules/news/Comments.php');
  372. $this->reload();
  373. }
  374. $this->Template->is28Update = true;
  375. $this->outputAndExit();
  376. }
  377. /**
  378. * Collations
  379. */
  380. if ($this->Input->post('FORM_SUBMIT') == 'tl_collation')
  381. {
  382. $arrTables = array();
  383. $strCharset = strtolower($GLOBALS['TL_CONFIG']['dbCharset']);
  384. $strCollation = $this->Input->post('dbCollation');
  385. try
  386. {
  387. $this->Database->query("ALTER DATABASE {$GLOBALS['TL_CONFIG']['dbDatabase']} DEFAULT CHARACTER SET $strCharset COLLATE $strCollation");
  388. }
  389. catch (Exception $e)
  390. {
  391. // Ignore
  392. }
  393. $objField = $this->Database->prepare("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME LIKE 'tl_%' AND !ISNULL(COLLATION_NAME)")
  394. ->execute($GLOBALS['TL_CONFIG']['dbDatabase']);
  395. while ($objField->next())
  396. {
  397. if (!in_array($objField->TABLE_NAME, $arrTables))
  398. {
  399. $this->Database->query("ALTER TABLE {$objField->TABLE_NAME} DEFAULT CHARACTER SET $strCharset COLLATE $strCollation");
  400. $arrTables[] = $objField->TABLE_NAME;
  401. }
  402. $strQuery = "ALTER TABLE {$objField->TABLE_NAME} CHANGE {$objField->COLUMN_NAME} {$objField->COLUMN_NAME} {$objField->COLUMN_TYPE} CHARACTER SET $strCharset COLLATE $strCollation";
  403. if ($objField->IS_NULLABLE == 'YES')
  404. {
  405. $strQuery .= " NULL";
  406. }
  407. else
  408. {
  409. $strQuery .= " NOT NULL DEFAULT '{$objField->COLUMN_DEFAULT}'";
  410. }
  411. $this->Database->query($strQuery);
  412. }
  413. $this->Config->update("\$GLOBALS['TL_CONFIG']['dbCollation']", $strCollation);
  414. $this->reload();
  415. }
  416. $arrOptions = array();
  417. $objCollation = $this->Database->prepare("SHOW COLLATION LIKE ?")
  418. ->execute($GLOBALS['TL_CONFIG']['dbCharset'] .'%');
  419. while ($objCollation->next())
  420. {
  421. $key = $objCollation->Collation;
  422. $arrOptions[$key] = sprintf('<option value="%s"%s>%s</option>',
  423. $key,
  424. (($key == $GLOBALS['TL_CONFIG']['dbCollation']) ? ' selected="selected"' : ''),
  425. $key);
  426. }
  427. ksort($arrOptions);
  428. $this->Template->collations = implode('', $arrOptions);
  429. /**
  430. * Update database tables
  431. */
  432. if ($this->Input->post('FORM_SUBMIT') == 'tl_tables')
  433. {
  434. $sql = deserialize($this->Input->post('sql'));
  435. if (is_array($sql))
  436. {
  437. foreach ($sql as $key)
  438. {
  439. if (isset($_SESSION['sql_commands'][$key]))
  440. {
  441. $this->Database->query(str_replace('DEFAULT CHARSET=utf8;', 'DEFAULT CHARSET=utf8 COLLATE ' . $GLOBALS['TL_CONFIG']['dbCollation'] . ';', $_SESSION['sql_commands'][$key]));
  442. }
  443. }
  444. }
  445. $_SESSION['sql_commands'] = array();
  446. $this->reload();
  447. }
  448. $this->Template->dbUpdate = $this->generateSqlForm();
  449. $this->Template->dbUpToDate = strlen($this->Template->dbUpdate) ? false : true;
  450. /**
  451. * Import the example website
  452. */
  453. if ($this->Input->post('FORM_SUBMIT') == 'tl_tutorial')
  454. {
  455. $this->Template->emptySelection = true;
  456. $strTemplate = basename($this->Input->post('template'));
  457. // Template selected
  458. if ($strTemplate != '' && file_exists(TL_ROOT . '/templates/' . $strTemplate))
  459. {
  460. $this->Config->update("\$GLOBALS['TL_CONFIG']['exampleWebsite']", time());
  461. $tables = preg_grep('/^tl_/i', $this->Database->listTables());
  462. // Truncate tables
  463. if (!isset($_POST['preserve']))
  464. {
  465. foreach ($tables as $table)
  466. {
  467. $this->Database->execute("TRUNCATE TABLE " . $table);
  468. }
  469. }
  470. // Import data
  471. $file = file(TL_ROOT . '/templates/' . $strTemplate);
  472. $sql = preg_grep('/^INSERT /', $file);
  473. foreach ($sql as $query)
  474. {
  475. $this->Database->execute($query);
  476. }
  477. $this->reload();
  478. }
  479. }
  480. $strTemplates = '<option value="">-</option>';
  481. foreach (scan(TL_ROOT . '/templates') as $strFile)
  482. {
  483. if (preg_match('/.sql$/', $strFile))
  484. {
  485. $strTemplates .= sprintf('<option value="%s">%s</option>', $strFile, specialchars($strFile));
  486. }
  487. }
  488. $this->Template->templates = $strTemplates;
  489. $this->Template->dateImported = $this->parseDate($GLOBALS['TL_CONFIG']['datimFormat'], $GLOBALS['TL_CONFIG']['exampleWebsite']);
  490. /**
  491. * Create an admin user
  492. */
  493. try
  494. {
  495. $objAdmin = $this->Database->execute("SELECT COUNT(*) AS total FROM tl_user WHERE admin=1");
  496. if ($objAdmin->total > 0)
  497. {
  498. $this->Template->adminCreated = true;
  499. }
  500. // Create an admin account
  501. elseif ($this->Input->post('FORM_SUBMIT') == 'tl_admin')
  502. {
  503. // Do not allow special characters
  504. if (preg_match('/[#\(\)\/<=>]/', html_entity_decode($this->Input->post('pass'))))
  505. {
  506. $this->Template->adminError = $GLOBALS['TL_LANG']['ERR']['extnd'];
  507. }
  508. // Passwords do not match
  509. elseif ($this->Input->post('pass') != $this->Input->post('confirm_pass'))
  510. {
  511. $this->Template->adminError = $GLOBALS['TL_LANG']['ERR']['passwordMatch'];
  512. }
  513. // Password too short
  514. elseif (utf8_strlen($this->Input->post('pass')) < $GLOBALS['TL_CONFIG']['minPasswordLength'])
  515. {
  516. $this->Template->adminError = sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], $GLOBALS['TL_CONFIG']['minPasswordLength']);
  517. }
  518. // Save data
  519. elseif(strlen($this->Input->post('name')) && strlen($this->Input->post('email', true)) && strlen($this->Input->post('username')))
  520. {
  521. $strSalt = substr(md5(uniqid('', true)), 0, 23);
  522. $strPassword = sha1($strSalt . $this->Input->post('pass'));
  523. $this->Database->prepare("INSERT INTO tl_user (tstamp, name, email, username, password, admin, showHelp, useRTE, thumbnails) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
  524. ->execute(time(), $this->Input->post('name'), $this->Input->post('email', true), $this->Input->post('username'), $strPassword . ':' . $strSalt, 1, 1, 1, 1);
  525. $this->Config->update("\$GLOBALS['TL_CONFIG']['adminEmail']", $this->Input->post('email', true));
  526. $this->reload();
  527. }
  528. $this->Template->adminName = $this->Input->post('name');
  529. $this->Template->adminEmail = $this->Input->post('email', true);
  530. $this->Template->adminUser = $this->Input->post('username');
  531. }
  532. }
  533. catch (Exception $e)
  534. {
  535. $this->Template->adminCreated = false;
  536. }
  537. /**
  538. * Clear the cron timestamps so the jobs are run
  539. */
  540. $this->Config->delete("\$GLOBALS['TL_CONFIG']['cron_hourly']");
  541. $this->Config->delete("\$GLOBALS['TL_CONFIG']['cron_daily']");
  542. $this->Config->delete("\$GLOBALS['TL_CONFIG']['cron_weekly']");
  543. /**
  544. * Output the template file
  545. */
  546. $this->outputAndExit();
  547. }
  548. /**
  549. * Generate a HTML form with update commands and return it as string
  550. * @return string
  551. */
  552. protected function generateSqlForm()
  553. {
  554. $count = 0;
  555. $return = '';
  556. $sql_command = $this->compileCommands();
  557. if (!count($sql_command))
  558. {
  559. return '';
  560. }
  561. $_SESSION['sql_commands'] = array();
  562. $arrOperations = array
  563. (
  564. 'CREATE' => $GLOBALS['TL_LANG']['tl_install']['CREATE'],
  565. 'ALTER_ADD' => $GLOBALS['TL_LANG']['tl_install']['ALTER_ADD'],
  566. 'ALTER_CHANGE' => $GLOBALS['TL_LANG']['tl_install']['ALTER_CHANGE'],
  567. 'ALTER_DROP' => $GLOBALS['TL_LANG']['tl_install']['ALTER_DROP'],
  568. 'DROP' => $GLOBALS['TL_LANG']['tl_install']['DROP']
  569. );
  570. foreach ($arrOperations as $command=>$label)
  571. {
  572. if (is_array($sql_command[$command]))
  573. {
  574. // Headline
  575. $return .= '
  576. <tr>
  577. <td colspan="2" class="tl_col_0">'.$label.'</td>
  578. </tr>';
  579. // Check all
  580. $return .= '
  581. <tr>
  582. <td class="tl_col_1"><input type="checkbox" id="check_all_' . $count . '" class="tl_checkbox" onclick="Backend.toggleCheckboxElements(this, \'' . strtolower($command) . '\')" /></td>
  583. <td class="tl_col_2"><label for="check_all_' . $count . '" style="color:#a6a6a6;"><em>Select all</em></label></td>
  584. </tr>';
  585. // Fields
  586. foreach ($sql_command[$command] as $vv)
  587. {
  588. $key = md5($vv);
  589. $_SESSION['sql_commands'][$key] = $vv;
  590. $return .= '
  591. <tr>
  592. <td class="tl_col_1"><input type="checkbox" name="sql[]" id="sql_'.$count.'" class="tl_checkbox ' . strtolower($command) . '" value="'.$key.'"'.((stristr($command, 'DROP') === false) ? ' checked="checked"' : '').' /></td>
  593. <td class="tl_col_2"><pre><label for="sql_'.$count++.'">'.$vv.'</label></pre></td>
  594. </tr>';
  595. }
  596. }
  597. }
  598. return '
  599. <table cellspacing="0" cellpadding="0" id="sql_table" style="margin-top:9px;" summary="Database modifications">'.$return.'
  600. </table>' . "\n";
  601. }
  602. /**
  603. * Compile a command array for each necessary database modification
  604. * @return array
  605. */
  606. protected function compileCommands()
  607. {
  608. $drop = array();
  609. $create = array();
  610. $return = array();
  611. $sql_current = $this->getFromDb();
  612. $sql_target = $this->getFromFile();
  613. // Create tables
  614. foreach (array_diff(array_keys($sql_target), array_keys($sql_current)) as $table)
  615. {
  616. $return['CREATE'][] = "CREATE TABLE `" . $table . "` (\n " . implode(",\n ", $sql_target[$table]['TABLE_FIELDS']) . (count($sql_target[$table]['TABLE_CREATE_DEFINITIONS']) ? ',' : '') . "\n " . implode(",\n ", $sql_target[$table]['TABLE_CREATE_DEFINITIONS']) . "\n)".$sql_target[$table]['TABLE_OPTIONS'].';';
  617. $create[] = $table;
  618. }
  619. // Add or change fields
  620. foreach ($sql_target as $k=>$v)
  621. {
  622. if (in_array($k, $create))
  623. {
  624. continue;
  625. }
  626. // Fields
  627. if (is_array($v['TABLE_FIELDS']))
  628. {
  629. foreach ($v['TABLE_FIELDS'] as $kk=>$vv)
  630. {
  631. if (!isset($sql_current[$k]['TABLE_FIELDS'][$kk]))
  632. {
  633. $return['ALTER_ADD'][] = 'ALTER TABLE `'.$k.'` ADD '.$vv.';';
  634. }
  635. elseif ($sql_current[$k]['TABLE_FIELDS'][$kk] != $vv)
  636. {
  637. $return['ALTER_CHANGE'][] = 'ALTER TABLE `'.$k.'` CHANGE `'.$kk.'` '.$vv.';';
  638. }
  639. }
  640. }
  641. // Create definitions
  642. if (is_array($v['TABLE_CREATE_DEFINITIONS']))
  643. {
  644. foreach ($v['TABLE_CREATE_DEFINITIONS'] as $kk=>$vv)
  645. {
  646. if (!isset($sql_current[$k]['TABLE_CREATE_DEFINITIONS'][$kk]))
  647. {
  648. $return['ALTER_ADD'][] = 'ALTER TABLE `'.$k.'` ADD '.$vv.';';
  649. }
  650. elseif ($sql_current[$k]['TABLE_CREATE_DEFINITIONS'][$kk] != str_replace('FULLTEXT ', '', $vv))
  651. {
  652. $return['ALTER_CHANGE'][] = 'ALTER TABLE `'.$k.'` DROP INDEX `'.$kk.'`, ADD '.$vv.';';
  653. }
  654. }
  655. }
  656. // Move auto_increment fields to the end of the array
  657. if (is_array($return['ALTER_ADD']))
  658. {
  659. foreach (preg_grep('/auto_increment/i', $return['ALTER_ADD']) as $kk=>$vv)
  660. {
  661. unset($return['ALTER_ADD'][$kk]);
  662. $return['ALTER_ADD'][$kk] = $vv;
  663. }
  664. }
  665. if (is_array($return['ALTER_CHANGE']))
  666. {
  667. foreach (preg_grep('/auto_increment/i', $return['ALTER_CHANGE']) as $kk=>$vv)
  668. {
  669. unset($return['ALTER_CHANGE'][$kk]);
  670. $return['ALTER_CHANGE'][$kk] = $vv;
  671. }
  672. }
  673. }
  674. // Drop tables
  675. foreach (array_diff(array_keys($sql_current), array_keys($sql_target)) as $table)
  676. {
  677. $return['DROP'][] = 'DROP TABLE `'.$table.'`;';
  678. $drop[] = $table;
  679. }
  680. // Drop fields
  681. foreach ($sql_current as $k=>$v)
  682. {
  683. if (!in_array($k, $drop))
  684. {
  685. // Fields
  686. if (is_array($v['TABLE_FIELDS']))
  687. {
  688. foreach ($v['TABLE_FIELDS'] as $kk=>$vv)
  689. {
  690. if (!isset($sql_target[$k]['TABLE_FIELDS'][$kk]))
  691. {
  692. $return['ALTER_DROP'][] = 'ALTER TABLE `'.$k.'` DROP `'.$kk.'`;';
  693. }
  694. }
  695. }
  696. // Create definitions
  697. if (is_array($v['TABLE_CREATE_DEFINITIONS']))
  698. {
  699. foreach ($v['TABLE_CREATE_DEFINITIONS'] as $kk=>$vv)
  700. {
  701. if (!isset($sql_target[$k]['TABLE_CREATE_DEFINITIONS'][$kk]))
  702. {
  703. $return['ALTER_DROP'][] = 'ALTER TABLE `'.$k.'` DROP INDEX `'.$kk.'`;';
  704. }
  705. }
  706. }
  707. }
  708. }
  709. return $return;
  710. }
  711. /**
  712. * Compile a table array from all SQL files and return it
  713. * @return array
  714. */
  715. protected function getFromFile()
  716. {
  717. $return = array();
  718. // Get all SQL files
  719. foreach (scan(TL_ROOT . '/system/modules') as $strModule)
  720. {
  721. if (strncmp($strModule, '.', 1) === 0 || strncmp($strModule, '__', 2) === 0)
  722. {
  723. continue;
  724. }
  725. $strFile = sprintf('%s/system/modules/%s/config/database.sql', TL_ROOT, $strModule);
  726. if (!file_exists($strFile))
  727. {
  728. continue;
  729. }
  730. $data = file($strFile);
  731. foreach ($data as $k=>$v)
  732. {
  733. $key_name = array();
  734. $subpatterns = array();
  735. // Unset comments and empty lines
  736. if (preg_match('/^[#-]+/i', $v) || !strlen(trim($v)))
  737. {
  738. unset($data[$k]);
  739. continue;
  740. }
  741. // Store table names
  742. if (preg_match('/^CREATE TABLE `([^`]+)`/i', $v, $subpatterns))
  743. {
  744. $table = $subpatterns[1];
  745. }
  746. // Get table options
  747. elseif (strlen($table) && preg_match('/^\)([^;]+);/i', $v, $subpatterns))
  748. {
  749. $return[$table]['TABLE_OPTIONS'] = $subpatterns[1];
  750. $table = '';
  751. }
  752. // Add fields
  753. elseif (strlen($table))
  754. {
  755. preg_match('/^[^`]*`([^`]+)`/i', trim($v), $key_name);
  756. $first = preg_replace('/\s[^\n\r]+/i', '', $key_name[0]);
  757. $key = $key_name[1];
  758. // Create definitions
  759. if (in_array($first, array('KEY', 'PRIMARY', 'PRIMARY KEY', 'FOREIGN', 'FOREIGN KEY', 'INDEX', 'UNIQUE', 'FULLTEXT', 'CHECK')))
  760. {
  761. $return[$table]['TABLE_CREATE_DEFINITIONS'][$key] = preg_replace('/,$/i', '', trim($v));
  762. }
  763. else
  764. {
  765. $return[$table]['TABLE_FIELDS'][$key] = preg_replace('/,$/i', '', trim($v));
  766. }
  767. }
  768. }
  769. }
  770. return $return;
  771. }
  772. /**
  773. * Compile a table array from the database and return it
  774. * @return array
  775. */
  776. protected function getFromDB()
  777. {
  778. $tables = preg_grep('/^tl_/i', $this->Database->listTables());
  779. if (!count($tables))
  780. {
  781. return array();
  782. }
  783. $return = array();
  784. foreach ($tables as $table)
  785. {
  786. $fields = $this->Database->listFields($table);
  787. foreach ($fields as $field)
  788. {
  789. $name = $field['name'];
  790. $field['name'] = '`'.$field['name'].'`';
  791. // Field type
  792. if (strlen($field['length']))
  793. {
  794. $field['type'] .= '(' . $field['length'] . (strlen($field['precision']) ? ',' . $field['precision'] : '') . ')';
  795. unset($field['length']);
  796. unset($field['precision']);
  797. }
  798. // Default values
  799. if (in_array(strtolower($field['type']), array('text', 'tinytext', 'mediumtext', 'longtext', 'blob', 'tinyblob', 'mediumblob', 'longblob')) || stristr($field['extra'], 'auto_increment'))
  800. {
  801. unset($field['default']);
  802. }
  803. elseif (is_null($field['default']) || strtolower($field['default']) == 'null')
  804. {
  805. $field['default'] = "default NULL";
  806. }
  807. else
  808. {
  809. $field['default'] = "default '" . $field['default'] . "'";
  810. }
  811. // Indices
  812. if (strlen($field['index']))
  813. {
  814. switch ($field['index'])
  815. {
  816. case 'PRIMARY':
  817. $return[$table]['TABLE_CREATE_DEFINITIONS'][$name] = 'PRIMARY KEY (`'.$name.'`)';
  818. break;
  819. case 'UNIQUE':
  820. $return[$table]['TABLE_CREATE_DEFINITIONS'][$name] = 'UNIQUE KEY `'.$name.'` (`'.$name.'`)';
  821. break;
  822. case 'FULLTEXT':
  823. $return[$table]['TABLE_CREATE_DEFINITIONS'][$name] = 'FULLTEXT KEY `'.$name.'` (`'.$name.'`)';
  824. break;
  825. default:
  826. $return[$table]['TABLE_CREATE_DEFINITIONS'][$name] = 'KEY `'.$name.'` (`'.$name.'`)';
  827. break;
  828. }
  829. unset($field['index']);
  830. }
  831. $return[$table]['TABLE_FIELDS'][$name] = trim(implode(' ', $field));
  832. }
  833. }
  834. return $return;
  835. }
  836. /**
  837. * Output the template file and exit
  838. */
  839. protected function outputAndExit()
  840. {
  841. $this->Template->theme = $this->getTheme();
  842. $this->Template->base = $this->Environment->base;
  843. $this->Template->language = $GLOBALS['TL_LANGUAGE'];
  844. $this->Template->charset = $GLOBALS['TL_CONFIG']['characterSet'];
  845. $this->Template->isMac = preg_match('/mac/i', $this->Environment->httpUserAgent);
  846. $this->Template->pageOffset = $this->Input->cookie('BE_PAGE_OFFSET');
  847. $this->Template->action = ampersand($this->Environment->request);
  848. $this->Template->output();
  849. exit;
  850. }
  851. }
  852. /**
  853. * Instantiate controller
  854. */
  855. $objInstallTool = new InstallTool();
  856. $objInstallTool->run();
  857. ?>