PageRenderTime 109ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/typo3/sysext/install/mod/class.tx_install.php

https://bitbucket.org/tritum_sw/typo3v4-core
PHP | 8476 lines | 6717 code | 543 blank | 1216 comment | 728 complexity | 476370d9fe6f6190da6e2ab928087c75 MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, BSD-3-Clause, BSD-2-Clause, AGPL-1.0, LGPL-3.0, GPL-3.0, MIT, LGPL-2.1
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
  6. * All rights reserved
  7. *
  8. * This script is part of the TYPO3 project. The TYPO3 project is
  9. * free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * The GNU General Public License can be found at
  15. * http://www.gnu.org/copyleft/gpl.html.
  16. * A copy is found in the textfile GPL.txt and important notices to the license
  17. * from the author is found in LICENSE.txt distributed with these scripts.
  18. *
  19. *
  20. * This script is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * This copyright notice MUST APPEAR in all copies of the script!
  26. ***************************************************************/
  27. /**
  28. * Contains the class for the Install Tool
  29. *
  30. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  31. * @author Ingmar Schlecht <ingmar@typo3.org>
  32. */
  33. // include requirements definition:
  34. require_once(t3lib_extMgm::extPath('install') . 'requirements.php');
  35. // include session handling
  36. require_once(t3lib_extMgm::extPath('install') . 'mod/class.tx_install_session.php');
  37. // include update classes
  38. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_charsetdefaults.php');
  39. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_compatversion.php');
  40. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_cscsplit.php');
  41. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_notinmenu.php');
  42. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_mergeadvanced.php');
  43. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_installsysexts.php');
  44. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_imagescols.php');
  45. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_installnewsysexts.php');
  46. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_statictemplates.php');
  47. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_t3skin.php');
  48. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_compressionlevel.php');
  49. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_migrateworkspaces.php');
  50. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_flagsfromsprite.php');
  51. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_addflexformstoacl.php');
  52. require_once(t3lib_extMgm::extPath('install') . 'updates/class.tx_coreupdates_imagelink.php');
  53. /**
  54. * Install Tool module
  55. *
  56. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  57. * @author Ingmar Schlecht <ingmar@typo3.org>
  58. * @package TYPO3
  59. * @subpackage tx_install
  60. */
  61. class tx_install extends t3lib_install {
  62. var $templateFilePath = 'typo3/sysext/install/Resources/Private/Templates/';
  63. var $template;
  64. var $javascript;
  65. var $stylesheets;
  66. var $markers = array();
  67. var $messages = array();
  68. var $errorMessages = array();
  69. var $mailMessage = '';
  70. var $action = ''; // The url that calls this script
  71. var $scriptSelf = 'index.php'; // The url that calls this script
  72. var $updateIdentity = 'TYPO3 Install Tool';
  73. var $headerStyle ='';
  74. var $setAllCheckBoxesByDefault=0;
  75. var $allowFileEditOutsite_typo3conf_dir=0;
  76. var $INSTALL =array(); // In constructor: is set to global GET/POST var TYPO3_INSTALL
  77. var $checkIMlzw = 0; // If set, lzw capabilities of the available ImageMagick installs are check by actually writing a gif-file and comparing size
  78. var $checkIM = 0; // If set, ImageMagick is checked.
  79. var $dumpImCommands=1; // If set, the image Magick commands are always outputted in the image processing checker
  80. var $mode = ''; // If set to "123" then only most vital information is displayed.
  81. var $step = 0; // If set to 1,2,3 or GO it signifies various functions.
  82. var $totalSteps = 4; // Can be changed by hook to define the total steps in 123 mode
  83. // internal
  84. var $passwordOK=0; // This is set, if the password check was ok. The function init() will exit if this is not set
  85. var $silent=1; // If set, the check routines don't add to the message-array
  86. var $sections=array(); // Used to gather the message information.
  87. var $fatalError=0; // This is set if some error occured that will definitely prevent TYpo3 from running.
  88. var $sendNoCacheHeaders=1;
  89. var $config_array = array( // Flags are set in this array if the options are available and checked ok.
  90. 'gd'=>0,
  91. 'gd_gif'=>0,
  92. 'gd_png'=>0,
  93. 'gd_jpg'=>0,
  94. 'freetype' => 0,
  95. 'safemode' => 0,
  96. 'dir_typo3temp' => 0,
  97. 'dir_temp' => 0,
  98. 'im_versions' => array(),
  99. 'im' => 0,
  100. 'sql.safe_mode_user' => '',
  101. 'mysqlConnect' => 0,
  102. 'no_database' => 0
  103. );
  104. var $typo3temp_path='';
  105. /**
  106. * the session handling object
  107. *
  108. * @var tx_install_session
  109. */
  110. protected $session = NULL;
  111. /**
  112. * the form protection instance used for creating and verifying form tokens
  113. *
  114. * @var t3lib_formprotection_InstallToolFormProtection
  115. */
  116. protected $formProtection = NULL;
  117. var $menuitems = array(
  118. 'config' => 'Basic Configuration',
  119. 'database' => 'Database Analyser',
  120. 'update' => 'Upgrade Wizard',
  121. 'images' => 'Image Processing',
  122. 'extConfig' => 'All Configuration',
  123. 'cleanup' => 'Clean up',
  124. 'phpinfo' => 'phpinfo()',
  125. 'typo3conf_edit' => 'Edit files in typo3conf/',
  126. 'about' => 'About',
  127. 'logout' => 'Logout from Install Tool',
  128. );
  129. // PHP modules which are required. Can be changed by hook in getMissingPhpModules()
  130. protected $requiredPhpModules = array(
  131. 'fileinfo',
  132. 'filter',
  133. 'gd',
  134. 'json',
  135. 'mysql',
  136. 'pcre',
  137. 'session',
  138. 'SPL',
  139. 'standard',
  140. 'openssl',
  141. 'xml',
  142. 'zlib'
  143. );
  144. /**
  145. * Constructor
  146. *
  147. * @return void
  148. */
  149. function __construct() {
  150. parent::__construct();
  151. if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword']) {
  152. $this->outputErrorAndExit('Install Tool deactivated.<br />You must enable it by setting a password in typo3conf/localconf.php. If you insert the line below, the password will be \'joh316\':<br /><br />$TYPO3_CONF_VARS[\'BE\'][\'installToolPassword\'] = \'bacb98acf97e0b6112b1d1b650b84971\';', 'Fatal error');
  153. }
  154. if ($this->sendNoCacheHeaders) {
  155. header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
  156. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  157. header('Expires: 0');
  158. header('Cache-Control: no-cache, must-revalidate');
  159. header('Pragma: no-cache');
  160. }
  161. // ****************************
  162. // Initializing incoming vars.
  163. // ****************************
  164. $this->INSTALL = t3lib_div::_GP('TYPO3_INSTALL');
  165. $this->mode = t3lib_div::_GP('mode');
  166. if ($this->mode !== '123') {
  167. $this->mode = '';
  168. }
  169. if (t3lib_div::_GP('step') === 'go') {
  170. $this->step = 'go';
  171. } else {
  172. $this->step = intval(t3lib_div::_GP('step'));
  173. }
  174. // Let DBAL decide whether to load itself
  175. $dbalLoaderFile = $this->backPath . 'sysext/dbal/class.tx_dbal_autoloader.php';
  176. if (@is_file($dbalLoaderFile)) {
  177. include($dbalLoaderFile);
  178. }
  179. if ($this->mode === '123') {
  180. // Check for mandatory PHP modules
  181. $missingPhpModules = $this->getMissingPhpModules();
  182. if (count($missingPhpModules) > 0) {
  183. throw new RuntimeException('TYPO3 Installation Error: The following PHP module(s) is/are missing: <em>' .
  184. implode(', ', $missingPhpModules) .
  185. '</em><br /><br />You need to install and enable these modules first to be able to install TYPO3.',
  186. 1294587482
  187. );
  188. }
  189. // Load saltedpasswords if possible
  190. $saltedpasswordsLoaderFile = $this->backPath . 'sysext/saltedpasswords/classes/class.tx_saltedpasswords_autoloader.php';
  191. if (@is_file($saltedpasswordsLoaderFile)) {
  192. include($saltedpasswordsLoaderFile);
  193. }
  194. }
  195. $this->redirect_url = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('redirect_url'));
  196. $this->INSTALL['type'] = '';
  197. if ($_GET['TYPO3_INSTALL']['type']) {
  198. $allowedTypes = array(
  199. 'config', 'database', 'update', 'images', 'extConfig',
  200. 'cleanup', 'phpinfo', 'typo3conf_edit', 'about', 'logout'
  201. );
  202. if (in_array($_GET['TYPO3_INSTALL']['type'], $allowedTypes)) {
  203. $this->INSTALL['type'] = $_GET['TYPO3_INSTALL']['type'];
  204. }
  205. }
  206. if ($this->step == 4) {
  207. $this->INSTALL['type'] = 'database';
  208. }
  209. // Hook to raise the counter for the total steps in the 1-2-3 installer
  210. if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['additionalSteps'])) {
  211. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['additionalSteps'] as $classData) {
  212. $hookObject = t3lib_div::getUserObj($classData);
  213. $this->totalSteps += (integer) $hookObject->executeAdditionalSteps($this);
  214. }
  215. }
  216. if ($this->mode=='123') {
  217. $tempItems = $this->menuitems;
  218. $this->menuitems = array(
  219. 'config' => $tempItems['config'],
  220. 'database' => $tempItems['database']
  221. );
  222. if (!$this->INSTALL['type'] || !isset($this->menuitems[$this->INSTALL['type']])) {
  223. $this->INSTALL['type'] = 'config';
  224. }
  225. } else {
  226. if (!$this->INSTALL['type'] || !isset($this->menuitems[$this->INSTALL['type']])) {
  227. $this->INSTALL['type'] = 'about';
  228. }
  229. }
  230. $this->action = $this->scriptSelf .
  231. '?TYPO3_INSTALL[type]=' . $this->INSTALL['type'] .
  232. ($this->mode? '&mode=' . $this->mode : '') .
  233. ($this->step? '&step=' . $this->step : '');
  234. $this->typo3temp_path = PATH_site.'typo3temp/';
  235. if (!is_dir($this->typo3temp_path) || !is_writeable($this->typo3temp_path)) {
  236. $this->outputErrorAndExit('Install Tool needs to write to typo3temp/. Make sure this directory is writeable by your webserver: ' . htmlspecialchars($this->typo3temp_path), 'Fatal error');
  237. }
  238. try {
  239. $this->session = t3lib_div::makeInstance('tx_install_session');
  240. } catch (Exception $exception) {
  241. $this->outputErrorAndExit($exception->getMessage());
  242. }
  243. // *******************
  244. // Check authorization
  245. // *******************
  246. if (!$this->session->hasSession()) {
  247. $this->session->startSession();
  248. }
  249. if ($this->session->isAuthorized() || $this->checkPassword()) {
  250. $this->passwordOK=1;
  251. $this->session->refreshSession();
  252. $enableInstallToolFile = PATH_typo3conf . 'ENABLE_INSTALL_TOOL';
  253. if (is_file ($enableInstallToolFile)) {
  254. // Extend the age of the ENABLE_INSTALL_TOOL file by one hour
  255. @touch($enableInstallToolFile);
  256. }
  257. if($this->redirect_url) {
  258. t3lib_utility_Http::redirect($this->redirect_url);
  259. }
  260. $this->formProtection = t3lib_formProtection_Factory::get(
  261. 't3lib_formprotection_InstallToolFormProtection'
  262. );
  263. $this->formProtection->injectInstallTool($this);
  264. } else {
  265. $this->loginForm();
  266. }
  267. }
  268. /**
  269. * Returns TRUE if submitted password is ok.
  270. *
  271. * If password is ok, set session as "authorized".
  272. *
  273. * @return boolean TRUE if the submitted password was ok and session was
  274. * authorized, FALSE otherwise
  275. */
  276. function checkPassword() {
  277. $p = t3lib_div::_GP('password');
  278. if ($p && md5($p) === $GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword']) {
  279. $this->session->setAuthorized();
  280. // Sending warning email
  281. $wEmail = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
  282. if ($wEmail) {
  283. $subject = 'Install Tool Login at "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"';
  284. $email_body = 'There has been an Install Tool login at TYPO3 site "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '" (' . t3lib_div::getIndpEnv('HTTP_HOST') . ') from remote address "' . t3lib_div::getIndpEnv('REMOTE_ADDR') . '" (' . t3lib_div::getIndpEnv('REMOTE_HOST') . ')';
  285. mail($wEmail,
  286. $subject,
  287. $email_body,
  288. 'From: TYPO3 Install Tool WARNING <>'
  289. );
  290. }
  291. return TRUE;
  292. } else {
  293. // Bad password, send warning:
  294. if ($p) {
  295. $wEmail = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
  296. if ($wEmail) {
  297. $subject="Install Tool Login ATTEMPT at '".$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']."'";
  298. $email_body="There has been an Install Tool login attempt at TYPO3 site '".$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']."' (".t3lib_div::getIndpEnv('HTTP_HOST').").
  299. The MD5 hash of the last 5 characters of the password tried was '".substr(md5($p), -5)."'
  300. REMOTE_ADDR was '".t3lib_div::getIndpEnv('REMOTE_ADDR')."' (".t3lib_div::getIndpEnv('REMOTE_HOST').')';
  301. mail($wEmail,
  302. $subject,
  303. $email_body,
  304. 'From: TYPO3 Install Tool WARNING <>'
  305. );
  306. }
  307. }
  308. return FALSE;
  309. }
  310. }
  311. /**
  312. * Create the HTML for the login form
  313. *
  314. * Reads and fills the template.
  315. * Substitutes subparts when wrong password has been given
  316. * or the session has expired
  317. *
  318. * @return void
  319. */
  320. function loginForm() {
  321. $password = t3lib_div::_GP('password');
  322. $redirect_url = $this->redirect_url ? $this->redirect_url : $this->action;
  323. // Get the template file
  324. $templateFile = @file_get_contents(
  325. PATH_site . $this->templateFilePath . 'LoginForm.html'
  326. );
  327. // Get the template part from the file
  328. $template = t3lib_parsehtml::getSubpart(
  329. $templateFile, '###TEMPLATE###'
  330. );
  331. // Password has been given, but this form is rendered again.
  332. // This means the given password was wrong
  333. if (!empty($password)) {
  334. // Get the subpart for the wrong password
  335. $wrongPasswordSubPart = t3lib_parsehtml::getSubpart(
  336. $template, '###WRONGPASSWORD###'
  337. );
  338. // Define the markers content
  339. $wrongPasswordMarkers = array(
  340. 'passwordMessage' => 'The password you just tried has this md5-value:',
  341. 'password' => md5($password)
  342. );
  343. // Fill the markers in the subpart
  344. $wrongPasswordSubPart = t3lib_parsehtml::substituteMarkerArray(
  345. $wrongPasswordSubPart,
  346. $wrongPasswordMarkers,
  347. '###|###',
  348. TRUE,
  349. TRUE
  350. );
  351. }
  352. // Session has expired
  353. if (!$this->session->isAuthorized() && $this->session->isExpired()) {
  354. // Get the subpart for the expired session message
  355. $sessionExpiredSubPart = t3lib_parsehtml::getSubpart(
  356. $template, '###SESSIONEXPIRED###'
  357. );
  358. // Define the markers content
  359. $sessionExpiredMarkers = array(
  360. 'message' => 'Your Install Tool session has expired'
  361. );
  362. // Fill the markers in the subpart
  363. $sessionExpiredSubPart = t3lib_parsehtml::substituteMarkerArray(
  364. $sessionExpiredSubPart,
  365. $sessionExpiredMarkers,
  366. '###|###',
  367. TRUE,
  368. TRUE
  369. );
  370. }
  371. // Substitute the subpart for the expired session in the template
  372. $template = t3lib_parsehtml::substituteSubpart(
  373. $template,
  374. '###SESSIONEXPIRED###',
  375. $sessionExpiredSubPart
  376. );
  377. // Substitute the subpart for the wrong password in the template
  378. $template = t3lib_parsehtml::substituteSubpart(
  379. $template,
  380. '###WRONGPASSWORD###',
  381. $wrongPasswordSubPart
  382. );
  383. // Define the markers content
  384. $markers = array(
  385. 'siteName' => 'Site: ' .
  386. htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']),
  387. 'headTitle' => 'Login to TYPO3 ' . TYPO3_version . ' Install Tool',
  388. 'redirectUrl' => htmlspecialchars($redirect_url),
  389. 'enterPassword' => 'Password',
  390. 'login' => 'Login',
  391. 'message' => '
  392. <p class="typo3-message message-information">
  393. The Install Tool Password is <em>not</em> the admin password
  394. of TYPO3.
  395. <br />
  396. The default password is <em>joh316</em>. Be sure to change it!
  397. <br /><br />
  398. If you don\'t know the current password, you can set a new
  399. one by setting the value of
  400. $TYPO3_CONF_VARS[\'BE\'][\'installToolPassword\'] in
  401. typo3conf/localconf.php to the md5() hash value of the
  402. password you desire.
  403. </p>
  404. '
  405. );
  406. // Fill the markers in the template
  407. $content = t3lib_parsehtml::substituteMarkerArray(
  408. $template,
  409. $markers,
  410. '###|###',
  411. TRUE,
  412. TRUE
  413. );
  414. // Send content to the page wrapper function
  415. $this->output($this->outputWrapper($content));
  416. }
  417. /**
  418. * Calling function that checks system, IM, GD, dirs, database
  419. * and lets you alter localconf.php
  420. *
  421. * This method is called from init.php to start the Install Tool.
  422. *
  423. * @return void
  424. */
  425. function init() {
  426. // Must be called after inclusion of init.php (or from init.php)
  427. if (!defined('PATH_typo3')) exit;
  428. if (!$this->passwordOK) exit;
  429. // Setting stuff...
  430. $this->check_mail();
  431. $this->setupGeneral();
  432. $this->generateConfigForm();
  433. if (count($this->messages)) {
  434. t3lib_utility_Debug::debug($this->messages);
  435. }
  436. if ($this->step) {
  437. $this->output($this->outputWrapper($this->stepOutput()));
  438. } else {
  439. // Menu...
  440. switch($this->INSTALL['type']) {
  441. case 'images':
  442. $this->checkIM=1;
  443. $this->checkTheConfig();
  444. $this->silent=0;
  445. $this->checkTheImageProcessing();
  446. break;
  447. case 'database':
  448. $this->checkTheConfig();
  449. $this->silent=0;
  450. $this->checkTheDatabase();
  451. break;
  452. case 'update':
  453. $this->checkDatabase();
  454. $this->silent=0;
  455. $this->updateWizard();
  456. break;
  457. case 'config':
  458. $this->silent=0;
  459. $this->checkIM=1;
  460. $this->message(
  461. 'About configuration',
  462. 'How to configure TYPO3',
  463. $this->generallyAboutConfiguration()
  464. );
  465. $isPhpCgi = (PHP_SAPI == 'fpm-fcgi' || PHP_SAPI == 'cgi' || PHP_SAPI == 'isapi' || PHP_SAPI == 'cgi-fcgi');
  466. $this->message(
  467. 'System Information',
  468. 'Your system has the following configuration',
  469. '
  470. <dl id="systemInformation">
  471. <dt>OS detected:</dt>
  472. <dd>' . (TYPO3_OS == 'WIN' ? 'WIN' : 'UNIX') .'</dd>
  473. <dt>CGI detected:</dt>
  474. <dd>' . ($isPhpCgi ? 'YES' : 'NO') . '</dd>
  475. <dt>PATH_thisScript:</dt>
  476. <dd>' . PATH_thisScript . '</dd>
  477. </dl>
  478. '
  479. );
  480. $this->checkTheConfig();
  481. $ext = 'Write config to localconf.php';
  482. if ($this->fatalError) {
  483. if (
  484. $this->config_array['no_database'] ||
  485. !$this->config_array['mysqlConnect']
  486. ) {
  487. $this->message($ext, 'Database not configured yet!', '
  488. <p>
  489. You need to specify database username,
  490. password and host as one of the first things.
  491. <br />
  492. Next you\'ll have to select a database to
  493. use with TYPO3.
  494. </p>
  495. <p>
  496. Use the form below.
  497. </p>
  498. ', 2);
  499. } else {
  500. $this->message($ext, 'Fatal error encountered!', '
  501. <p>
  502. Somewhere above a fatal configuration
  503. problem is encountered.
  504. Please make sure that you\'ve fixed this
  505. error before you submit the configuration.
  506. TYPO3 will not run if this problem is not
  507. fixed!
  508. <br />
  509. You should also check all warnings that may
  510. appear.
  511. </p>
  512. ', 2);
  513. }
  514. } elseif ($this->mode=='123') {
  515. if (!$this->fatalError) {
  516. $this->message($ext, 'Basic configuration completed', '
  517. <p>
  518. You have no fatal errors in your basic
  519. configuration.
  520. You may have warnings though. Please pay
  521. attention to them!
  522. However you may continue and install the
  523. database.
  524. </p>
  525. <p>
  526. <strong>
  527. <span style="color:#f00;">Step 2: </span>
  528. </strong>
  529. <a href="' . $this->scriptSelf .
  530. '?TYPO3_INSTALL[type]=database' .
  531. ($this->mode ? '&mode=' . rawurlencode($this->mode) : '') .
  532. '">Click here to install the database.</a>
  533. </p>
  534. ', -1, 1);
  535. }
  536. }
  537. $this->message($ext, 'Very Important: Changing Image Processing settings', '
  538. <p>
  539. When you change the settings for Image Processing
  540. you <em>must</em> take into account
  541. that <em>old images</em> may still be in typo3temp/
  542. folder and prevent new files from being generated!
  543. <br />
  544. This is especially important to know, if you\'re
  545. trying to set up image processing for the very first
  546. time.
  547. <br />
  548. The problem is solved by <a href="' .
  549. htmlspecialchars($this->setScriptName('cleanup')) .
  550. '">clearing the typo3temp/ folder</a>.
  551. Also make sure to clear the cache_pages table.
  552. </p>
  553. ', 1, 1);
  554. $this->message($ext, 'Very Important: Changing Encryption Key setting', '
  555. <p>
  556. When you change the setting for the Encryption Key
  557. you <em>must</em> take into account that a change to
  558. this value might invalidate temporary information,
  559. URLs etc.
  560. <br />
  561. The problem is solved by <a href="' .
  562. htmlspecialchars($this->setScriptName('cleanup')) .
  563. '">clearing the typo3temp/ folder</a>.
  564. Also make sure to clear the cache_pages table.
  565. </p>
  566. ', 1, 1);
  567. $this->message($ext, 'Update localconf.php', '
  568. <p>
  569. This form updates the localconf.php file with the
  570. suggested values you see below. The values are based
  571. on the analysis above.
  572. <br />
  573. You can change the values in case you have
  574. alternatives to the suggested defaults.
  575. <br />
  576. By this final step you will configure TYPO3 for
  577. immediate use provided that you have no fatal errors
  578. left above.
  579. </p>' . $this->setupGeneral('get_form') . '
  580. ', 0, 1);
  581. $this->output($this->outputWrapper($this->printAll()));
  582. break;
  583. case 'extConfig':
  584. $this->silent=0;
  585. $this->generateConfigForm('get_form');
  586. // Get the template file
  587. $templateFile = @file_get_contents(
  588. PATH_site . $this->templateFilePath . 'InitExtConfig.html'
  589. );
  590. // Get the template part from the file
  591. $template = t3lib_parsehtml::getSubpart(
  592. $templateFile, '###TEMPLATE###'
  593. );
  594. // Define the markers content
  595. $markers = array(
  596. 'action' => $this->action,
  597. 'content' => $this->printAll(),
  598. 'write' => 'Write to localconf.php',
  599. 'notice' => 'NOTICE:',
  600. 'explanation' => '
  601. By clicking this button, localconf.php is updated
  602. with new values for the parameters listed above!
  603. '
  604. );
  605. // Fill the markers in the template
  606. $content = t3lib_parsehtml::substituteMarkerArray(
  607. $template,
  608. $markers,
  609. '###|###',
  610. TRUE,
  611. FALSE
  612. );
  613. // Send content to the page wrapper function
  614. $this->output($this->outputWrapper($content));
  615. break;
  616. case 'cleanup':
  617. $this->checkTheConfig();
  618. $this->silent=0;
  619. $this->cleanupManager();
  620. break;
  621. case 'phpinfo':
  622. $this->silent=0;
  623. $this->phpinformation();
  624. break;
  625. case 'typo3conf_edit':
  626. $this->silent=0;
  627. $this->typo3conf_edit();
  628. break;
  629. case 'logout':
  630. $enableInstallToolFile = PATH_site . 'typo3conf/ENABLE_INSTALL_TOOL';
  631. if (is_file($enableInstallToolFile) && trim(file_get_contents($enableInstallToolFile)) !== 'KEEP_FILE') {
  632. unlink(PATH_typo3conf . 'ENABLE_INSTALL_TOOL');
  633. }
  634. $this->formProtection->clean();
  635. $this->session->destroySession();
  636. t3lib_utility_Http::redirect($this->scriptSelf);
  637. break;
  638. case 'about':
  639. default:
  640. $this->silent=0;
  641. $this->message('About', 'Warning - very important!', $this->securityRisk().$this->alterPasswordForm(), 2);
  642. $this->message('About', 'Using this script', '
  643. <p>
  644. Installing TYPO3 has always been a hot topic on the
  645. mailing list and forums. Therefore we\'ve developed
  646. this tool which will help you through configuration
  647. and testing.
  648. <br />
  649. There are three primary steps for you to take:
  650. </p>
  651. <p>
  652. <strong>1: Basic Configuration</strong>
  653. <br />
  654. In this step your PHP-configuration is checked. If
  655. there are any settings that will prevent TYPO3 from
  656. running correctly you\'ll get warnings and errors
  657. with a description of the problem.
  658. <br />
  659. You\'ll have to enter a database username, password
  660. and hostname. Then you can choose to create a new
  661. database or select an existing one.
  662. <br />
  663. Finally the image processing settings are entered
  664. and verified and you can choose to let the script
  665. update the configuration file,
  666. typo3conf/localconf.php with the suggested settings.
  667. </p>
  668. <p>
  669. <strong>2: Database Analyser</strong>
  670. <br />
  671. In this step you can either install a new database
  672. or update the database from any previous TYPO3
  673. version.
  674. <br />
  675. You can also get an overview of extra/missing
  676. fields/tables in the database compared to a raw
  677. sql-file.
  678. <br />
  679. The database is also verified against your
  680. \'tables.php\' configuration ($TCA) and you can
  681. even see suggestions to entries in $TCA or new
  682. fields in the database.
  683. </p>
  684. <p>
  685. <strong>3: Upgrade Wizard</strong>
  686. <br />
  687. Here you will find update methods taking care of
  688. changes to the TYPO3 core which are not backwards
  689. compatible.
  690. <br />
  691. It is recommended to run this wizard after every
  692. update to make sure everything will still work
  693. flawlessly.
  694. </p>
  695. <p>
  696. <strong>4: Image Processing</strong>
  697. <br />
  698. This step is a visual guide to verify your
  699. configuration of the image processing software.
  700. <br />
  701. You\'ll be presented to a list of images that should
  702. all match in pairs. If some irregularity appears,
  703. you\'ll get a warning. Thus you\'re able to track an
  704. error before you\'ll discover it on your website.
  705. </p>
  706. <p>
  707. <strong>5: All Configuration</strong>
  708. <br />
  709. This gives you access to any of the configuration
  710. options in the TYPO3_CONF_VARS array. Every option
  711. is also presented with a comment explaining what it
  712. does.
  713. </p>
  714. <p>
  715. <strong>6: Cleanup</strong>
  716. <br />
  717. Here you can clean up the temporary files in typo3temp/
  718. folder and the tables used for caching of data in
  719. your database.
  720. </p>
  721. ');
  722. $this->message('About', 'Why is this script stand-alone?', '
  723. <p>
  724. You would think that this script should rather be a
  725. module in the backend and access-controlled to only
  726. admin-users from the database. But that\'s not how
  727. it works.
  728. <br />
  729. The reason is, that this script must not be
  730. depending on the success of the configuration of
  731. TYPO3 and whether or not there is a working database
  732. behind. Therefore the script is invoked from the
  733. backend init.php file, which allows access if the
  734. constant \'TYPO3_enterInstallScript\' has been
  735. defined and is not FALSE. That is and should be the
  736. case <em>only</em> when calling the script
  737. \'typo3/install/index.php\' - this script!
  738. </p>
  739. ');
  740. $headCode='Header legend';
  741. $this->message($headCode, 'Notice!', '
  742. <p>
  743. Indicates that something is important to be aware
  744. of.
  745. <br />
  746. This does <em>not</em> indicate an error.
  747. </p>
  748. ', 1);
  749. $this->message($headCode, 'Just information', '
  750. <p>
  751. This is a simple message with some information about
  752. something.
  753. </p>
  754. ');
  755. $this->message($headCode, 'Check was successful', '
  756. <p>
  757. Indicates that something was checked and returned an
  758. expected result.
  759. </p>
  760. ', -1);
  761. $this->message($headCode, 'Warning!', '
  762. <p>
  763. Indicates that something may very well cause trouble
  764. and you should definitely look into it before
  765. proceeding.
  766. <br />
  767. This indicates a <em>potential</em> error.
  768. </p>
  769. ', 2);
  770. $this->message($headCode, 'Error!', '
  771. <p>
  772. Indicates that something is definitely wrong and
  773. that TYPO3 will most likely not perform as expected
  774. if this problem is not solved.
  775. <br />
  776. This indicates an actual error.
  777. </p>
  778. ', 3);
  779. $this->output($this->outputWrapper($this->printAll()));
  780. break;
  781. }
  782. }
  783. }
  784. /**
  785. * Controls the step 1-2-3-go process
  786. *
  787. * @return string The content to output to the screen
  788. */
  789. function stepOutput() {
  790. // Get the template file
  791. $templateFile = @file_get_contents(
  792. PATH_site . $this->templateFilePath . 'StepOutput.html'
  793. );
  794. // Get the template part from the file
  795. $template = t3lib_parsehtml::getSubpart(
  796. $templateFile, '###TEMPLATE###'
  797. );
  798. // Define the markers content
  799. $markers = array(
  800. 'stepHeader' => $this->stepHeader(),
  801. 'notice' => 'Skip this wizard (for power users only)',
  802. 'skip123' => $this->scriptSelf
  803. );
  804. $this->checkTheConfig();
  805. $error_missingConnect = '
  806. <p class="typo3-message message-error">
  807. <strong>
  808. There is no connection to the database!
  809. </strong>
  810. <br />
  811. (Username: <em>' . htmlspecialchars(TYPO3_db_username) . '</em>,
  812. Host: <em>' . htmlspecialchars(TYPO3_db_host) . '</em>,
  813. Using Password: YES)
  814. <br />
  815. Go to Step 1 and enter a valid username and password!
  816. </p>
  817. ';
  818. $error_missingDB = '
  819. <p class="typo3-message message-error">
  820. <strong>
  821. There is no access to the database (<em>' . htmlspecialchars(TYPO3_db) . '</em>)!
  822. </strong>
  823. <br />
  824. Go to Step 2 and select a valid database!
  825. </p>
  826. ';
  827. // only get the number of tables if it is not the first two steps in the 123-installer
  828. // (= no DB connection yet)
  829. $whichTables = ($this->step != 1 && $this->step != 2 ? $this->sqlHandler->getListOfTables() : array());
  830. $error_emptyDB = '
  831. <p class="typo3-message message-error">
  832. <strong>
  833. The database is still empty. There are no tables!
  834. </strong>
  835. <br />
  836. Go to Step 3 and import a database!
  837. </p>
  838. ';
  839. // Hook to override and add steps to the 1-2-3 installer
  840. if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['stepOutput'])) {
  841. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['stepOutput'] as $classData) {
  842. $hookObject = t3lib_div::getUserObj($classData);
  843. $hookObject->executeStepOutput($markers, $this->step, $this);
  844. }
  845. }
  846. // Use the default steps when there is no override
  847. if (!$markers['header'] && !$markers['step']) {
  848. switch(strtolower($this->step)) {
  849. case 1:
  850. // Get the subpart for the first step
  851. $step1SubPart = t3lib_parsehtml::getSubpart(
  852. $templateFile, '###STEP1###'
  853. );
  854. // Add header marker for main template
  855. $markers['header'] = 'Welcome to the TYPO3 Install Tool';
  856. // Define the markers content for the subpart
  857. $step1SubPartMarkers = array(
  858. 'llIntroduction' => '
  859. <p>
  860. TYPO3 is an enterprise content management system
  861. that is powerful, yet easy to install.
  862. </p>
  863. <p>
  864. In three simple steps you\'ll be ready to add content to your website.
  865. </p>
  866. ',
  867. 'step' => $this->step + 1,
  868. 'action' => htmlspecialchars($this->action),
  869. 'continue' => 'Continue'
  870. );
  871. // Add step marker for main template
  872. $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
  873. $step1SubPart,
  874. $step1SubPartMarkers,
  875. '###|###',
  876. TRUE,
  877. FALSE
  878. );
  879. break;
  880. case 2:
  881. // Get the subpart for the second step
  882. $step2SubPart = t3lib_parsehtml::getSubpart(
  883. $templateFile, '###STEP2###'
  884. );
  885. // Add header marker for main template
  886. $markers['header'] = 'Connect to your database host';
  887. // Define the markers content for the subpart
  888. $step2SubPartMarkers = array(
  889. 'step' => $this->step + 1,
  890. 'action' => htmlspecialchars($this->action),
  891. 'encryptionKey' => $this->createEncryptionKey(),
  892. 'branch' => TYPO3_branch,
  893. 'labelUsername' => 'Username',
  894. 'username' => htmlspecialchars(TYPO3_db_username),
  895. 'labelPassword' => 'Password',
  896. 'password' => htmlspecialchars(TYPO3_db_password),
  897. 'labelHost' => 'Host',
  898. 'host' => TYPO3_db_host ? htmlspecialchars(TYPO3_db_host) : 'localhost',
  899. 'continue' => 'Continue',
  900. 'llDescription' => 'If you have not already created a username and password to access the database, please do so now. This can be done using tools provided by your host.'
  901. );
  902. // Add step marker for main template
  903. $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
  904. $step2SubPart,
  905. $step2SubPartMarkers,
  906. '###|###',
  907. TRUE,
  908. FALSE
  909. );
  910. break;
  911. case 3:
  912. // Add header marker for main template
  913. $markers['header'] = 'Select database';
  914. // There should be a database host connection at this point
  915. if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(
  916. TYPO3_db_host, TYPO3_db_username, TYPO3_db_password
  917. )) {
  918. // Get the subpart for the third step
  919. $step3SubPart = t3lib_parsehtml::getSubpart(
  920. $templateFile, '###STEP3###'
  921. );
  922. // Get the subpart for the database options
  923. $step3DatabaseOptionsSubPart = t3lib_parsehtml::getSubpart(
  924. $step3SubPart, '###DATABASEOPTIONS###'
  925. );
  926. $dbArr = $this->getDatabaseList();
  927. $dbIncluded = 0;
  928. $step3DatabaseOptions = array();
  929. foreach ($dbArr as $dbname) {
  930. // Define the markers content for database options
  931. $step3DatabaseOptionMarkers = array(
  932. 'databaseValue' => htmlspecialchars($dbname),
  933. 'databaseSelected' => $dbname == TYPO3_db ? 'selected="selected"' : '',
  934. 'databaseName' => htmlspecialchars($dbname)
  935. );
  936. // Add the option HTML to an array
  937. $step3DatabaseOptions[] = t3lib_parsehtml::substituteMarkerArray(
  938. $step3DatabaseOptionsSubPart,
  939. $step3DatabaseOptionMarkers,
  940. '###|###',
  941. TRUE,
  942. TRUE
  943. );
  944. if ($dbname==TYPO3_db) $dbIncluded=1;
  945. }
  946. if (!$dbIncluded && TYPO3_db) {
  947. // // Define the markers content when no access
  948. $step3DatabaseOptionMarkers = array(
  949. 'databaseValue' => htmlspecialchars(TYPO3_db),
  950. 'databaseSelected' => 'selected="selected"',
  951. 'databaseName' => htmlspecialchars(TYPO3_db) . ' (NO ACCESS!)'
  952. );
  953. // Add the option HTML to an array
  954. $step3DatabaseOptions[] = t3lib_parsehtml::substituteMarkerArray(
  955. $step3DatabaseOptionsSubPart,
  956. $step3DatabaseOptionMarkers,
  957. '###|###',
  958. TRUE,
  959. TRUE
  960. );
  961. }
  962. $usePatternList = FALSE;
  963. $createDatabaseAllowed = $this->checkCreateDatabasePrivileges();
  964. if ($createDatabaseAllowed === TRUE) {
  965. $formFieldAttributesNew = 'checked="checked"';
  966. $llRemark1 = 'Enter a name for your TYPO3 database.';
  967. } elseif (is_array($createDatabaseAllowed)) {
  968. $llRemark1 = 'Enter a name for your TYPO3 database.';
  969. $llDbPatternRemark = 'The name has to match one of these names/patterns (% is a wild card):';
  970. $llDbPatternList = '<li>' . implode('</li><li>', $createDatabaseAllowed) . '</li>';
  971. $usePatternList = TRUE;
  972. } else {
  973. $formFieldAttributesNew = 'disabled="disabled"';
  974. $formFieldAttributesSelect = 'checked="checked"';
  975. $llRemark1 = 'You have no permissions to create new databases.';
  976. }
  977. // Substitute the subpart for the database options
  978. $content = t3lib_parsehtml::substituteSubpart(
  979. $step3SubPart,
  980. '###DATABASEOPTIONS###',
  981. implode(LF, $step3DatabaseOptions)
  982. );
  983. if ($usePatternList === FALSE) {
  984. $content = t3lib_parsehtml::substituteSubpart(
  985. $content,
  986. '###DATABASE_NAME_PATTERNS###',
  987. ''
  988. );
  989. }
  990. // Define the markers content
  991. $step3SubPartMarkers = array(
  992. 'step' => $this->step + 1,
  993. 'llOptions' => 'You have two options:',
  994. 'action' => htmlspecialchars($this->action),
  995. 'llOption1' => 'Create a new database (recommended):',
  996. 'llRemark1' => $llRemark1,
  997. 'll_Db_Pattern_Remark' => $llDbPatternRemark,
  998. 'll_Db_Pattern_List' => $llDbPatternList,
  999. 'formFieldAttributesNew' => $formFieldAttributesNew,
  1000. 'formFieldAttributesSelect' => $formFieldAttributesSelect,
  1001. 'llOption2' => 'Select an EMPTY existing database:',
  1002. 'llRemark2' => 'Any tables used by TYPO3 will be overwritten.',
  1003. 'continue' => 'Continue'
  1004. );
  1005. // Add step marker for main template
  1006. $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
  1007. $content,
  1008. $step3SubPartMarkers,
  1009. '###|###',
  1010. TRUE,
  1011. TRUE
  1012. );
  1013. } else {
  1014. // Add step marker for main template when no connection
  1015. $markers['step'] = $error_missingConnect;
  1016. }
  1017. break;
  1018. case 4:
  1019. // Add header marker for main template
  1020. $markers['header'] = 'Import the Database Tables';
  1021. // There should be a database host connection at this point
  1022. if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(
  1023. TYPO3_db_host, TYPO3_db_username, TYPO3_db_password
  1024. )) {
  1025. // The selected database should be accessible
  1026. if ($GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
  1027. // Get the subpart for the fourth step
  1028. $step4SubPart = t3lib_parsehtml::getSubpart(
  1029. $templateFile, '###STEP4###'
  1030. );
  1031. // Get the subpart for the database type options
  1032. $step4DatabaseTypeOptionsSubPart = t3lib_parsehtml::getSubpart(
  1033. $step4SubPart, '###DATABASETYPEOPTIONS###'
  1034. );
  1035. $sFiles = t3lib_div::getFilesInDir(PATH_typo3conf, 'sql', 1, 1);
  1036. // Check if default database scheme "database.sql" already exists, otherwise create it
  1037. if (!strstr(implode(',', $sFiles).',', '/database.sql,')) {
  1038. array_unshift($sFiles, 'Default TYPO3 Tables');
  1039. }
  1040. $step4DatabaseTypeOptions = array();
  1041. foreach ($sFiles as $f) {
  1042. if ($f=='Default TYPO3 Tables') $key='CURRENT_TABLES+STATIC';
  1043. else $key=htmlspecialchars($f);
  1044. // Define the markers content for database type subpart
  1045. $step4DatabaseTypeOptionMarkers = array(
  1046. 'databaseTypeValue' => 'import|' . $key,
  1047. 'databaseName' => htmlspecialchars(basename($f))
  1048. );
  1049. // Add the option HTML to an array
  1050. $step4DatabaseTypeOptions[] = t3lib_parsehtml::substituteMarkerArray(
  1051. $step4DatabaseTypeOptionsSubPart,
  1052. $step4DatabaseTypeOptionMarkers,
  1053. '###|###',
  1054. TRUE,
  1055. FALSE
  1056. );
  1057. }
  1058. // Substitute the subpart for the database type options
  1059. $content = t3lib_parsehtml::substituteSubpart(
  1060. $step4SubPart,
  1061. '###DATABASETYPEOPTIONS###',
  1062. implode(LF, $step4DatabaseTypeOptions)
  1063. );
  1064. // Define the markers content
  1065. $step4SubPartMarkers = array(
  1066. 'llSummary' => 'Database summary:',
  1067. 'llUsername' => 'Username:',
  1068. 'username' => htmlspecialchars(TYPO3_db_username),
  1069. 'llHost' => 'Host:',
  1070. 'host' => htmlspecialchars(TYPO3_db_host),
  1071. 'llDatabase' => 'Database:',
  1072. 'database' => htmlspecialchars(TYPO3_db),
  1073. 'llNumberTables' => 'Number of tables:',
  1074. 'numberTables' => count($whichTables),
  1075. 'action' => htmlspecialchars($this->action),
  1076. 'llDatabaseType' => 'Select database contents:',
  1077. 'label' => 'Import database'
  1078. );
  1079. // Add step marker for main template
  1080. $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
  1081. $content,
  1082. $step4SubPartMarkers,
  1083. '###|###',
  1084. TRUE,
  1085. TRUE
  1086. );
  1087. } else {
  1088. // Add step marker for main template when no database
  1089. $markers['step'] = $error_missingDB;
  1090. }
  1091. } else {
  1092. // Add step marker for main template when no connection
  1093. $markers['step'] = $error_missingConnect;
  1094. }
  1095. break;
  1096. case 'go':
  1097. // Add header marker for main template
  1098. $markers['header'] = 'Congratulations!';
  1099. // There should be a database host connection at this point
  1100. if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(
  1101. TYPO3_db_host, TYPO3_db_username, TYPO3_db_password
  1102. )) {
  1103. // The selected database should be accessible
  1104. if ($GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
  1105. // The database should contain tables
  1106. if (count($whichTables)) {
  1107. // Get the subpart for the go step
  1108. $stepGoSubPart = t3lib_parsehtml::getSubpart(
  1109. $templateFile, '###STEPGO###'
  1110. );
  1111. // Define the markers content
  1112. $stepGoSubPartMarkers = array(
  1113. 'messageBasicFinished' => $this->messageBasicFinished(),
  1114. 'llImportant' => 'Important Security Warning',
  1115. 'securityRisk' => $this->securityRisk(),
  1116. 'llSwitchMode' => '
  1117. <a href="' . $this->scriptSelf . '">
  1118. Change the Install Tool password here
  1119. </a>
  1120. '
  1121. );
  1122. // Add step marker for main template
  1123. $markers['step'] = t3lib_parsehtml::substituteMarkerArray(
  1124. $stepGoSubPart,
  1125. $stepGoSubPartMarkers,
  1126. '###|###',
  1127. TRUE,
  1128. TRUE
  1129. );
  1130. } else {
  1131. // Add step marker for main template when empty database
  1132. $markers['step'] = $error_emptyDB;
  1133. }
  1134. } else {
  1135. // Add step marker for main template when no database
  1136. $markers['step'] = $error_missingDB;
  1137. }
  1138. } else {
  1139. // Add step marker for main template when no connection
  1140. $markers['step'] = $error_missingConnect;
  1141. }
  1142. break;
  1143. }
  1144. }
  1145. // Fill the markers in the template
  1146. $content = t3lib_parsehtml::substituteMarkerArray(
  1147. $template,
  1148. $markers,
  1149. '###|###',
  1150. TRUE,
  1151. FALSE
  1152. );
  1153. return $content;
  1154. }
  1155. /**
  1156. * Calling the functions that checks the system
  1157. *
  1158. * @return void
  1159. */
  1160. function checkTheConfig() {
  1161. // Order important:
  1162. $this->checkDirs();
  1163. $this->checkConfiguration();
  1164. $this->checkExtensions();
  1165. if (TYPO3_OS=='WIN') {
  1166. $paths=array($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'], $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path'], 'c:\\php\\imagemagick\\', 'c:\\php\\GraphicsMagick\\', 'c:\\apache\\ImageMagick\\', 'c:\\apache\\GraphicsMagick\\');
  1167. if (!isset($_SERVER['PATH'])) {
  1168. $serverPath = array_change_key_case($_SERVER, CASE_UPPER);
  1169. $paths = array_merge($paths, explode(';', $serverPath['PATH']));
  1170. } else {
  1171. $paths = array_merge($paths, explode(';', $_SERVER['PATH']));
  1172. }
  1173. } else {
  1174. $paths=array($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'], $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path'], '/usr/local/bin/', '/usr/bin/', '/usr/X11R6/bin/', '/opt/local/bin/');
  1175. $paths = array_merge($paths, explode(':', $_SERVER['PATH']));
  1176. }
  1177. $paths = array_unique($paths);
  1178. asort($paths);
  1179. if (t3lib_utility_PhpOptions::isSafeModeEnabled()) {
  1180. $paths=array(ini_get('safe_mode_exec_dir'), '/usr/local/php/bin/');
  1181. }
  1182. if ($this->INSTALL['checkIM']['lzw']) {
  1183. $this->checkIMlzw=1;
  1184. }
  1185. if ($this->INSTALL['checkIM']['path']) {
  1186. $paths[]=trim($this->INSTALL['checkIM']['path']);
  1187. }
  1188. if ($this->checkIM) $this->checkImageMagick($paths);
  1189. $this->checkDatabase();
  1190. }
  1191. /**
  1192. * Editing files in typo3conf directory (or elsewhere if enabled)
  1193. *
  1194. * @return void
  1195. */
  1196. function typo3conf_edit() {
  1197. // default:
  1198. $EDIT_path = PATH_typo3conf;
  1199. if ($this->allowFileEditOutsite_typo3conf_dir && $this->INSTALL['FILE']['EDIT_path']) {
  1200. if (t3lib_div::validPathStr($this->INSTALL['FILE']['EDIT_path']) && substr($this->INSTALL['FILE']['EDIT_path'], -1)=='/') {
  1201. $tmp_path = PATH_site.$this->INSTALL['FILE']['EDIT_path'];
  1202. if (is_dir($tmp_path)) {
  1203. $EDIT_path=$tmp_path;
  1204. } else {
  1205. $this->errorMessages[] = '
  1206. \'' . $tmp_path . '\' was not directory
  1207. ';
  1208. }
  1209. } else {
  1210. $this->errorMessages[] = '
  1211. Bad directory name (must be like t3lib/ or media/script/)
  1212. ';
  1213. }
  1214. }
  1215. $headCode = 'Edit files in '.basename($EDIT_path).'/';
  1216. $messages = '';
  1217. if ($this->INSTALL['SAVE_FILE']) {
  1218. $save_to_file = $this->INSTALL['FILE']['name'];
  1219. if (@is_file($save_to_file)) {
  1220. $save_to_file_md5 = md5($save_to_file);
  1221. if (isset($this->INSTALL['FILE'][$save_to_file_md5]) && t3lib_div::isFirstPartOfStr($save_to_file, $EDIT_path.'') && substr($save_to_file, -1)!='~' && !strstr($save_to_file, '_bak')) {
  1222. $this->INSTALL['typo3conf_files'] = $save_to_file;
  1223. $save_fileContent = $this->INSTALL['FILE'][$save_to_file_md5];
  1224. if ($this->INSTALL['FILE']['win_to_unix_br']) {
  1225. $save_fileContent = str_replace(CRLF, LF, $save_fileContent);
  1226. }
  1227. $backupFile = $this->getBackupFilename($save_to_file);
  1228. if ($this->INSTALL['FILE']['backup']) {
  1229. if (@is_file($backupFile)) { unlink($backupFile); }
  1230. rename($save_to_file, $backupFile);
  1231. $messages .= '
  1232. Backup written to <strong>' . $backupFile . '</strong>
  1233. <br />
  1234. ';
  1235. }
  1236. t3lib_div::writeFile($save_to_file, $save_fileContent);
  1237. $messages .= '
  1238. File saved: <strong>' . $save_to_file . '</strong>
  1239. <br />
  1240. MD5-sum: ' . $this->INSTALL['FILE']['prevMD5'] . ' (prev)
  1241. <br />
  1242. MD5-sum: ' . md5($save_fileContent) . ' (new)
  1243. <br />
  1244. ';
  1245. }
  1246. }
  1247. }
  1248. // Filelist:
  1249. // Get the template file
  1250. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'Typo3ConfEdit.html');
  1251. // Get the template part from the file
  1252. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  1253. // Get the subpart for the files
  1254. $filesSubpart = t3lib_parsehtml::getSubpart($template, '###FILES###');
  1255. $files = array();
  1256. $typo3conf_files = t3lib_div::getFilesInDir($EDIT_path, '', 1, 1);
  1257. $fileFound = 0;
  1258. foreach ($typo3conf_files as $k => $file) {
  1259. // Delete temp_CACHED files if option is set
  1260. if ( $this->INSTALL['delTempCached'] && preg_match('|/temp_CACHED_[a-z0-9_]+\.php|', $file)) {
  1261. unlink($file);
  1262. continue;
  1263. }
  1264. if ($this->INSTALL['typo3conf_files'] && !strcmp($this->INSTALL['typo3conf_files'], $file)) {
  1265. $fileFound = 1;
  1266. }
  1267. // Define the markers content for the files subpart
  1268. $filesMarkers = array(
  1269. 'editUrl' => $this->action . '&amp;TYPO3_INSTALL[typo3conf_files]=' . rawurlencode($file) . ($this->allowFileEditOutsite_typo3conf_dir ? '&amp;TYPO3_INSTALL[FILE][EDIT_path]=' . rawurlencode($this->INSTALL['FILE']['EDIT_path']) : '') . '#confEditFileList',
  1270. 'fileName' => basename($file),
  1271. 'fileSize' => t3lib_div::formatSize(filesize($file)),
  1272. 'class' => $this->INSTALL['typo3conf_files'] && !strcmp($this->INSTALL['typo3conf_files'], $file) ? 'class="act"' : ''
  1273. );
  1274. // Fill the markers in the subpart
  1275. $files[] = t3lib_parsehtml::substituteMarkerArray(
  1276. $filesSubpart,
  1277. $filesMarkers,
  1278. '###|###',
  1279. TRUE,
  1280. FALSE
  1281. );
  1282. }
  1283. if ($fileFound && @is_file($this->INSTALL['typo3conf_files'])) {
  1284. $backupFile = $this->getBackupFilename($this->INSTALL['typo3conf_files']);
  1285. $fileContent = t3lib_div::getUrl($this->INSTALL['typo3conf_files']);
  1286. // Get the subpart to edit the files
  1287. $fileEditTemplate = t3lib_parsehtml::getSubpart($template, '###FILEEDIT###');
  1288. $allowFileEditOutsideTypo3ConfDirSubPart = '';
  1289. if (substr($this->INSTALL['typo3conf_files'], -1) != '~' && !strstr($this->INSTALL['typo3conf_files'], '_bak')) {
  1290. // Get the subpart to show the save button
  1291. $showSaveButtonSubPart = t3lib_parsehtml::getSubpart($fileEditTemplate, '###SHOWSAVEBUTTON###');
  1292. }
  1293. if ($this->allowFileEditOutsite_typo3conf_dir) {
  1294. // Get the subpart to show if files are allowed outside the directory typo3conf
  1295. $allowFileEditOutsideTypo3ConfDirSubPart = t3lib_parsehtml::getSubpart($fileEditTemplate, '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###');
  1296. }
  1297. // Substitute the subpart for the save button
  1298. $fileEditContent = t3lib_parsehtml::substituteSubpart(
  1299. $fileEditTemplate,
  1300. '###SHOWSAVEBUTTON###',
  1301. $showSaveButtonSubPart
  1302. );
  1303. // Substitute the subpart to show if files are allowed outside the directory typo3conf
  1304. $fileEditContent = t3lib_parsehtml::substituteSubpart(
  1305. $fileEditContent,
  1306. '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###',
  1307. $allowFileEditOutsideTypo3ConfDirSubPart
  1308. );
  1309. // Define the markers content for subpart to edit the files
  1310. $fileEditMarkers = array(
  1311. 'messages' => !empty($messages) ? '<p class="typo3-message message-warning">' . $messages . '</p>' : '',
  1312. 'action' => $this->action . '#fileEditHeader',
  1313. 'saveFile' => 'Save file',
  1314. 'close' => 'Close',
  1315. 'llEditing' => 'Editing file:',
  1316. 'file' => $this->INSTALL['typo3conf_files'],
  1317. 'md5Sum' => 'MD5-sum: ' . md5($fileContent),
  1318. 'fileName' => $this->INSTALL['typo3conf_files'],
  1319. 'fileEditPath' => $this->INSTALL['FILE']['EDIT_path'],
  1320. 'filePreviousMd5' => md5($fileContent),
  1321. 'fileMd5' => md5($this->INSTALL['typo3conf_files']),
  1322. 'fileContent' => t3lib_div::formatForTextarea($fileContent),
  1323. 'winToUnixBrChecked' => TYPO3_OS == 'WIN' ? '' : 'checked="checked"',
  1324. 'winToUnixBr' => 'Convert Windows linebreaks (13-10) to Unix (10)',
  1325. 'backupChecked' => @is_file($backupFile) ? 'checked="checked"' : '',
  1326. 'backup' => 'Make backup copy (rename to ' . basename($backupFile) . ')'
  1327. );
  1328. // Fill the markers in the subpart to edit the files
  1329. $fileEditContent = t3lib_parsehtml::substituteMarkerArray(
  1330. $fileEditContent,
  1331. $fileEditMarkers,
  1332. '###|###',
  1333. TRUE,
  1334. FALSE
  1335. );
  1336. }
  1337. if ($this->allowFileEditOutsite_typo3conf_dir) {
  1338. // Get the subpart to show if files are allowed outside the directory typo3conf
  1339. $allowFileEditOutsideTypo3ConfDirSubPart = t3lib_parsehtml::getSubpart($template, '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###');
  1340. // Define the markers content
  1341. $allowFileEditOutsideTypo3ConfDirMarkers = array(
  1342. 'action' => $this->action,
  1343. 'pathSite' => PATH_site,
  1344. 'editPath' => $this->INSTALL['FILE']['EDIT_path'],
  1345. 'set' => 'Set'
  1346. );
  1347. // Fill the markers in the subpart
  1348. $allowFileEditOutsideTypo3ConfDirSubPart = t3lib_parsehtml::substituteMarkerArray(
  1349. $allowFileEditOutsideTypo3ConfDirSubPart,
  1350. $allowFileEditOutsideTypo3ConfDirMarkers,
  1351. '###|###',
  1352. TRUE,
  1353. FALSE
  1354. );
  1355. }
  1356. // Substitute the subpart to edit the file
  1357. $fileListContent = t3lib_parsehtml::substituteSubpart(
  1358. $template,
  1359. '###FILEEDIT###',
  1360. $fileEditContent
  1361. );
  1362. // Substitute the subpart when files can be edited outside typo3conf directory
  1363. $fileListContent = t3lib_parsehtml::substituteSubpart(
  1364. $fileListContent,
  1365. '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###',
  1366. $allowFileEditOutsideTypo3ConfDirSubPart
  1367. );
  1368. // Substitute the subpart for the files
  1369. $fileListContent = t3lib_parsehtml::substituteSubpart(
  1370. $fileListContent,
  1371. '###FILES###',
  1372. implode(LF, $files)
  1373. );
  1374. // Define the markers content
  1375. $fileListMarkers = array(
  1376. 'editPath' => '(' . $EDIT_path . ')',
  1377. 'deleteTempCachedUrl' => $this->action . '&amp;TYPO3_INSTALL[delTempCached]=1',
  1378. 'deleteTempCached' => 'Delete temp_CACHED* files'
  1379. );
  1380. // Fill the markers
  1381. $fileListContent = t3lib_parsehtml::substituteMarkerArray(
  1382. $fileListContent,
  1383. $fileListMarkers,
  1384. '###|###',
  1385. TRUE,
  1386. FALSE
  1387. );
  1388. // Add the content to the message array
  1389. $this->message($headCode, 'Files in folder', $fileListContent);
  1390. // Output the page
  1391. $this->output($this->outputWrapper($this->printAll()));
  1392. }
  1393. /**
  1394. * Outputs system information
  1395. *
  1396. * @return void
  1397. */
  1398. function phpinformation() {
  1399. $headCode = 'PHP information';
  1400. $sVar = t3lib_div::getIndpEnv('_ARRAY');
  1401. $sVar['CONST: PHP_OS']=PHP_OS;
  1402. $sVar['CONST: TYPO3_OS']=TYPO3_OS;
  1403. $sVar['CONST: PATH_thisScript']=PATH_thisScript;
  1404. $sVar['CONST: php_sapi_name()']=PHP_SAPI;
  1405. $sVar['OTHER: TYPO3_VERSION']=TYPO3_version;
  1406. $sVar['OTHER: PHP_VERSION']=phpversion();
  1407. $sVar['imagecreatefromgif()']=function_exists('imagecreatefromgif');
  1408. $sVar['imagecreatefrompng()']=function_exists('imagecreatefrompng');
  1409. $sVar['imagecreatefromjpeg()']=function_exists('imagecreatefromjpeg');
  1410. $sVar['imagegif()']=function_exists('imagegif');
  1411. $sVar['imagepng()']=function_exists('imagepng');
  1412. $sVar['imagejpeg()']=function_exists('imagejpeg');
  1413. $sVar['imagettftext()']=function_exists('imagettftext');
  1414. $sVar['OTHER: IMAGE_TYPES']=function_exists('imagetypes') ? imagetypes() : 0;
  1415. $sVar['OTHER: memory_limit']=ini_get('memory_limit');
  1416. $gE_keys = explode(',', 'SERVER_PORT,SERVER_SOFTWARE,GATEWAY_INTERFACE,SCRIPT_NAME,PATH_TRANSLATED');
  1417. foreach ($gE_keys as $k) {
  1418. $sVar['SERVER: '.$k]=$_SERVER[$k];
  1419. }
  1420. $gE_keys = explode(',', 'image_processing,gdlib,gdlib_png,im,im_path,im_path_lzw,im_version_5,im_negate_mask,im_imvMaskState,im_combine_filename');
  1421. foreach ($gE_keys as $k) {
  1422. $sVar['T3CV_GFX: '.$k]=$GLOBALS['TYPO3_CONF_VARS']['GFX'][$k];
  1423. }
  1424. $debugInfo = array(
  1425. '### DEBUG SYSTEM INFORMATION - START ###'
  1426. );
  1427. foreach ($sVar as $kkk => $vvv) {
  1428. $debugInfo[]=str_pad(substr($kkk, 0, 20), 20).': '.$vvv;
  1429. }
  1430. $debugInfo[]='### DEBUG SYSTEM INFORMATION - END ###';
  1431. // Get the template file
  1432. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'PhpInformation.html');
  1433. // Get the template part from the file
  1434. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  1435. // Define the markers content
  1436. $markers = array(
  1437. 'explanation' => 'Please copy/paste the information from this text field into an email or bug-report as "Debug System Information" whenever you wish to get support or report problems. This information helps others to check if your system has some obvious misconfiguration and you\'ll get your help faster!',
  1438. 'debugInfo' => t3lib_div::formatForTextarea(implode(LF, $debugInfo))
  1439. );
  1440. // Fill the markers
  1441. $content = t3lib_parsehtml::substituteMarkerArray(
  1442. $template,
  1443. $markers,
  1444. '###|###',
  1445. TRUE,
  1446. FALSE
  1447. );
  1448. // Add the content to the message array
  1449. $this->message($headCode, 'DEBUG information', $content);
  1450. // Start with various server information
  1451. $getEnvArray = array();
  1452. $gE_keys = explode(',', 'QUERY_STRING,HTTP_ACCEPT,HTTP_ACCEPT_ENCODING,HTTP_ACCEPT_LANGUAGE,HTTP_CONNECTION,HTTP_COOKIE,HTTP_HOST,HTTP_USER_AGENT,REMOTE_ADDR,REMOTE_HOST,REMOTE_PORT,SERVER_ADDR,SERVER_ADMIN,SERVER_NAME,SERVER_PORT,SERVER_SIGNATURE,SERVER_SOFTWARE,GATEWAY_INTERFACE,SERVER_PROTOCOL,REQUEST_METHOD,SCRIPT_NAME,PATH_TRANSLATED,HTTP_REFERER,PATH_INFO');
  1453. foreach ($gE_keys as $k) {
  1454. $getEnvArray[$k] = getenv($k);
  1455. }
  1456. $this->message($headCode, 't3lib_div::getIndpEnv()', $this->viewArray(t3lib_div::getIndpEnv('_ARRAY')));
  1457. $this->message($headCode, 'getenv()', $this->viewArray($getEnvArray));
  1458. $this->message($headCode, '_ENV', $this->viewArray($_ENV));
  1459. $this->message($headCode, '_SERVER', $this->viewArray($_SERVER));
  1460. $this->message($headCode, '_COOKIE', $this->viewArray($_COOKIE));
  1461. $this->message($headCode, '_GET', $this->viewArray($_GET));
  1462. // Start with the phpinfo() part
  1463. ob_start();
  1464. phpinfo();
  1465. $contents = explode('<body>', ob_get_contents());
  1466. ob_end_clean();
  1467. $contents = explode('</body>', $contents[1]);
  1468. // Do code cleaning: phpinfo() is not XHTML1.1 compliant
  1469. $phpinfo = str_replace('<font', '<span', $contents[0]);
  1470. $phpinfo = str_replace('</font', '</span', $phpinfo);
  1471. $phpinfo = str_replace('<img border="0"', '<img', $phpinfo);
  1472. $phpinfo = str_replace('<a name=', '<a id=', $phpinfo);
  1473. // Add phpinfo() to the message array
  1474. $this->message($headCode, 'phpinfo()', '
  1475. <div class="phpinfo">
  1476. ' . $phpinfo . '
  1477. </div>
  1478. ');
  1479. // Output the page
  1480. $this->output($this->outputWrapper($this->printAll()));
  1481. }
  1482. /*******************************
  1483. *
  1484. * cleanup manager
  1485. *
  1486. *******************************/
  1487. /**
  1488. * Provides a tool cleaning up various tables in the database
  1489. *
  1490. * @return void
  1491. * @author Robert Lemke <rl@robertlemke.de>
  1492. * @todo Add more functionality ...
  1493. */
  1494. function cleanupManager() {
  1495. $headCode = 'Clean up your TYPO3 installation';
  1496. $this->message($headCode, 'Database cache tables', '
  1497. <p>
  1498. <strong>Clear cached image sizes</strong>
  1499. <br />
  1500. Clears the cache used for memorizing sizes of all images used in
  1501. your website. This information is cached in order to gain
  1502. performance and will be stored each time a new image is being
  1503. displayed in the frontend.
  1504. </p>
  1505. <p>
  1506. You should <em>Clear All Cache</em> in the backend after
  1507. clearing this cache.
  1508. </p>
  1509. ');
  1510. $tables = $this->sqlHandler->getListOfTables();
  1511. $action = $this->INSTALL['cleanup_type'];
  1512. if (($action == 'cache_imagesizes' || $action == 'all') && isset ($tables['cache_imagesizes'])) {
  1513. $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cache_imagesizes');
  1514. }
  1515. $cleanupType = array (
  1516. 'all' => 'Clean up everything',
  1517. );
  1518. // Get cache_imagesizes info
  1519. if (isset ($tables['cache_imagesizes'])) {
  1520. $cleanupType['cache_imagesizes'] = 'Clear cached image sizes only';
  1521. $cachedImageSizesCounter = intval($GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cache_imagesizes'));
  1522. } else {
  1523. $this->message($headCode, 'Table cache_imagesizes does not exist!', '
  1524. <p>
  1525. The table cache_imagesizes was not found. Please check your
  1526. database settings in Basic Configuration and compare your
  1527. table definition with the Database Analyzer.
  1528. </p>
  1529. ', 2);
  1530. $cachedImageSizesCounter = 'unknown';
  1531. }
  1532. // Get the template file
  1533. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CleanUpManager.html');
  1534. // Get the template part from the file
  1535. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  1536. // Get the subpart for the 'Clean up' dropdown
  1537. $cleanUpOptionsSubpart = t3lib_parsehtml::getSubpart($template, '###CLEANUPOPTIONS###');
  1538. $cleanUpOptions = array();
  1539. foreach ($cleanupType as $cleanUpKey => $cleanUpValue) {
  1540. // Define the markers content
  1541. $cleanUpMarkers = array(
  1542. 'value' => htmlspecialchars($cleanUpKey),
  1543. 'data' => htmlspecialchars($cleanUpValue)
  1544. );
  1545. // Fill the markers in the subpart
  1546. $cleanUpOptions[] = t3lib_parsehtml::substituteMarkerArray(
  1547. $cleanUpOptionsSubpart,
  1548. $cleanUpMarkers,
  1549. '###|###',
  1550. TRUE,
  1551. FALSE
  1552. );
  1553. }
  1554. // Substitute the subpart for the 'Clean up' dropdown
  1555. $content = t3lib_parsehtml::substituteSubpart(
  1556. $template,
  1557. '###CLEANUPOPTIONS###',
  1558. implode(LF, $cleanUpOptions)
  1559. );
  1560. // Define the markers content
  1561. $markers = array(
  1562. 'numberCached' => 'Number cached image sizes:',
  1563. 'number' => $cachedImageSizesCounter,
  1564. 'action' => $this->action,
  1565. 'cleanUp' => 'Clean up',
  1566. 'execute' => 'Execute'
  1567. );
  1568. // Fill the markers
  1569. $content = t3lib_parsehtml::substituteMarkerArray(
  1570. $content,
  1571. $markers,
  1572. '###|###',
  1573. TRUE,
  1574. FALSE
  1575. );
  1576. // Add the content to the message array
  1577. $this->message($headCode, 'Statistics', $content, 1);
  1578. $this->message($headCode, 'typo3temp/ folder', '
  1579. <p>
  1580. TYPO3 uses this directory for temporary files, mainly processed
  1581. and cached images.
  1582. <br />
  1583. The filenames are very cryptic; They are unique representations
  1584. of the file properties made by md5-hashing a serialized array
  1585. with information.
  1586. <br />
  1587. Anyway this directory may contain many thousand files and a lot
  1588. of them may be of no use anymore.
  1589. </p>
  1590. <p>
  1591. With this test you can delete the files in this folder. When you
  1592. do that, you should also clear the cache database tables
  1593. afterwards.
  1594. </p>
  1595. ');
  1596. if (!$this->config_array['dir_typo3temp']) {
  1597. $this->message('typo3temp/ directory', 'typo3temp/ not writable!', '
  1598. <p>
  1599. You must make typo3temp/ write enabled before you can
  1600. proceed with this test.
  1601. </p>
  1602. ', 2);
  1603. $this->output($this->outputWrapper($this->printAll()));
  1604. return;
  1605. }
  1606. // Run through files
  1607. $fileCounter = 0;
  1608. $deleteCounter = 0;
  1609. $criteriaMatch = 0;
  1610. $tmap=array('day'=>1, 'week'=>7, 'month'=>30);
  1611. $tt = $this->INSTALL['typo3temp_delete'];
  1612. $subdir = $this->INSTALL['typo3temp_subdir'];
  1613. if (strlen($subdir) && !preg_match('/^[[:alnum:]_]+\/$/', $subdir)) die('subdir "'.$subdir.'" was not allowed!');
  1614. $action = $this->INSTALL['typo3temp_action'];
  1615. $d = @dir($this->typo3temp_path.$subdir);
  1616. if (is_object($d)) {
  1617. while($entry=$d->read()) {
  1618. $theFile = $this->typo3temp_path.$subdir.$entry;
  1619. if (@is_file($theFile)) {
  1620. $ok = 0;
  1621. $fileCounter++;
  1622. if ($tt) {
  1623. if (t3lib_utility_Math::canBeInterpretedAsInteger($tt)) {
  1624. if (filesize($theFile) > $tt*1024) $ok=1;
  1625. } else {
  1626. if (fileatime($theFile) < $GLOBALS['EXEC_TIME'] - (intval($tmap[$tt]) * 60 * 60 * 24)) {
  1627. $ok = 1;
  1628. }
  1629. }
  1630. } else {
  1631. $ok = 1;
  1632. }
  1633. if ($ok) {
  1634. $hashPart=substr(basename($theFile), -14, 10);
  1635. // This is a kind of check that the file being deleted has a 10 char hash in it
  1636. if (!preg_match('/[^a-f0-9]/', $hashPart) || substr($theFile, -6)==='.cache' || substr($theFile, -4)==='.tbl' || substr(basename($theFile), 0, 8)==='install_') {
  1637. if ($action && $deleteCounter<$action) {
  1638. $deleteCounter++;
  1639. unlink($theFile);
  1640. } else {
  1641. $criteriaMatch++;
  1642. }
  1643. }
  1644. }
  1645. }
  1646. }
  1647. $d->close();
  1648. }
  1649. // Find sub-dirs:
  1650. $subdirRegistry = array(''=>'');
  1651. $d = @dir($this->typo3temp_path);
  1652. if (is_object($d)) {
  1653. while($entry=$d->read()) {
  1654. $theFile = $entry;
  1655. if (@is_dir($this->typo3temp_path.$theFile) && $theFile!='..' && $theFile!='.') {
  1656. $subdirRegistry[$theFile.'/'] = $theFile.'/ (Files: '.count(t3lib_div::getFilesInDir($this->typo3temp_path.$theFile)).')';
  1657. }
  1658. }
  1659. }
  1660. $deleteType=array(
  1661. '0' => 'All',
  1662. 'day' => 'Last access more than a day ago',
  1663. 'week' => 'Last access more than a week ago',
  1664. 'month' => 'Last access more than a month ago',
  1665. '10' => 'Filesize greater than 10KB',
  1666. '50' => 'Filesize greater than 50KB',
  1667. '100' => 'Filesize greater than 100KB'
  1668. );
  1669. $actionType=array(
  1670. '0' => "Don't delete, just display statistics",
  1671. '100' => 'Delete 100',
  1672. '500' => 'Delete 500',
  1673. '1000' => 'Delete 1000'
  1674. );
  1675. // Get the template file
  1676. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'Typo3TempManager.html');
  1677. // Get the template part from the file
  1678. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  1679. // Get the subpart for 'Delete files by condition' dropdown
  1680. $deleteOptionsSubpart = t3lib_parsehtml::getSubpart($template, '###DELETEOPTIONS###');
  1681. $deleteOptions = array();
  1682. foreach ($deleteType as $deleteKey => $deleteValue) {
  1683. // Define the markers content
  1684. $deleteMarkers = array(
  1685. 'value' => htmlspecialchars($deleteKey),
  1686. 'selected' => !strcmp($deleteKey, $tt) ? 'selected="selected"' : '',
  1687. 'data' => htmlspecialchars($deleteValue)
  1688. );
  1689. // Fill the markers in the subpart
  1690. $deleteOptions[] = t3lib_parsehtml::substituteMarkerArray(
  1691. $deleteOptionsSubpart,
  1692. $deleteMarkers,
  1693. '###|###',
  1694. TRUE,
  1695. FALSE
  1696. );
  1697. }
  1698. // Substitute the subpart for 'Delete files by condition' dropdown
  1699. $content = t3lib_parsehtml::substituteSubpart(
  1700. $template,
  1701. '###DELETEOPTIONS###',
  1702. implode(LF, $deleteOptions)
  1703. );
  1704. // Get the subpart for 'Number of files at a time' dropdown
  1705. $actionOptionsSubpart = t3lib_parsehtml::getSubpart($template, '###ACTIONOPTIONS###');
  1706. $actionOptions = array();
  1707. foreach ($actionType as $actionKey => $actionValue) {
  1708. // Define the markers content
  1709. $actionMarkers = array(
  1710. 'value' => htmlspecialchars($actionKey),
  1711. 'data' => htmlspecialchars($actionValue)
  1712. );
  1713. // Fill the markers in the subpart
  1714. $actionOptions[] = t3lib_parsehtml::substituteMarkerArray(
  1715. $actionOptionsSubpart,
  1716. $actionMarkers,
  1717. '###|###',
  1718. TRUE,
  1719. FALSE
  1720. );
  1721. }
  1722. // Substitute the subpart for 'Number of files at a time' dropdown
  1723. $content = t3lib_parsehtml::substituteSubpart(
  1724. $content,
  1725. '###ACTIONOPTIONS###',
  1726. implode(LF, $actionOptions)
  1727. );
  1728. // Get the subpart for 'From sub-directory' dropdown
  1729. $subDirectoryOptionsSubpart = t3lib_parsehtml::getSubpart($template, '###SUBDIRECTORYOPTIONS###');
  1730. $subDirectoryOptions = array();
  1731. foreach ($subdirRegistry as $subDirectoryKey => $subDirectoryValue) {
  1732. // Define the markers content
  1733. $subDirectoryMarkers = array(
  1734. 'value' => htmlspecialchars($subDirectoryKey),
  1735. 'selected' => !strcmp($subDirectoryKey, $this->INSTALL['typo3temp_subdir']) ? 'selected="selected"' : '',
  1736. 'data' => htmlspecialchars($subDirectoryValue)
  1737. );
  1738. // Fill the markers in the subpart
  1739. $subDirectoryOptions[] = t3lib_parsehtml::substituteMarkerArray(
  1740. $subDirectoryOptionsSubpart,
  1741. $subDirectoryMarkers,
  1742. '###|###',
  1743. TRUE,
  1744. FALSE
  1745. );
  1746. }
  1747. // Substitute the subpart for 'From sub-directory' dropdown
  1748. $content = t3lib_parsehtml::substituteSubpart(
  1749. $content,
  1750. '###SUBDIRECTORYOPTIONS###',
  1751. implode(LF, $subDirectoryOptions)
  1752. );
  1753. // Define the markers content
  1754. $markers = array(
  1755. 'numberTemporary' => 'Number of temporary files:',
  1756. 'numberMatching' => 'Number matching:',
  1757. 'numberDeleted' => 'Number deleted:',
  1758. 'temporary' => ($fileCounter - $deleteCounter),
  1759. 'matching' => $criteriaMatch,
  1760. 'deleteType' => '<span>' . htmlspecialchars($deleteType[$tt]) . '</span>',
  1761. 'deleted' => $deleteCounter,
  1762. 'deleteCondition' => 'Delete files by condition',
  1763. 'numberFiles' => 'Number of files at a time:',
  1764. 'fromSubdirectory' => 'From sub-directory:',
  1765. 'execute' => 'Execute',
  1766. 'explanation' => '
  1767. <p>
  1768. This tool will delete files only if the last 10 characters
  1769. before the extension (3 chars+\'.\') are hexadecimal valid
  1770. ciphers, which are lowercase a-f and 0-9.
  1771. </p>
  1772. '
  1773. );
  1774. // Fill the markers
  1775. $content = t3lib_parsehtml::substituteMarkerArray(
  1776. $content,
  1777. $markers,
  1778. '###|###',
  1779. TRUE,
  1780. FALSE
  1781. );
  1782. // Add the content to the message array
  1783. $this->message($headCode, 'Statistics', $content, 1);
  1784. // Output the page
  1785. $this->output($this->outputWrapper($this->printAll()));
  1786. }
  1787. /*******************************
  1788. *
  1789. * CONFIGURATION FORM
  1790. *
  1791. ********************************/
  1792. /**
  1793. * Creating the form for editing the TYPO3_CONF_VARS options.
  1794. *
  1795. * @param string $type If get_form, display form, otherwise checks and store in localconf.php
  1796. * @return void
  1797. */
  1798. function generateConfigForm($type='') {
  1799. $default_config_content = t3lib_div::getUrl(PATH_t3lib . 'stddb/DefaultSettings.php');
  1800. $commentArr = $this->getDefaultConfigArrayComments($default_config_content);
  1801. switch($type) {
  1802. case 'get_form':
  1803. // Get the template file
  1804. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'GenerateConfigForm.html');
  1805. // Get the template part from the file
  1806. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  1807. foreach ($GLOBALS['TYPO3_CONF_VARS'] as $k => $va) {
  1808. $ext='['.$k.']';
  1809. $this->message($ext, '$TYPO3_CONF_VARS[\''.$k.'\']', $commentArr[0][$k], 1);
  1810. foreach ($va as $vk => $value) {
  1811. if (isset($GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$k][$vk])) {
  1812. // Don't allow editing stuff which is added by extensions
  1813. // Make sure we fix potentially duplicated entries from older setups
  1814. $potentialValue = str_replace(array("'.chr(10).'", "' . LF . '"), array(LF, LF), $value);
  1815. while (preg_match('/' . preg_quote($GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$k][$vk], '/') . '$/', '', $potentialValue)) {
  1816. $potentialValue = preg_replace(
  1817. '/' . preg_quote($GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$k][$vk], '/') . '$/',
  1818. '',
  1819. $potentialValue
  1820. );
  1821. }
  1822. $value = $potentialValue;
  1823. }
  1824. $textAreaSubpart = '';
  1825. $booleanSubpart = '';
  1826. $textLineSubpart = '';
  1827. $description = trim($commentArr[1][$k][$vk]);
  1828. $isTextarea = preg_match('/^(<.*?>)?string \(textarea\)/i', $description) ? TRUE : FALSE;
  1829. $doNotRender = preg_match('/^(<.*?>)?string \(exclude\)/i', $description) ? TRUE : FALSE;
  1830. if (!is_array($value) && !$doNotRender && ($this->checkForBadString($value) || $isTextarea)) {
  1831. $k2 = '['.$vk.']';
  1832. if ($isTextarea) {
  1833. // Get the subpart for a textarea
  1834. $textAreaSubpart = t3lib_parsehtml::getSubpart($template, '###TEXTAREA###');
  1835. // Define the markers content
  1836. $textAreaMarkers = array(
  1837. 'id' => $k . '-' . $vk,
  1838. 'name' => 'TYPO3_INSTALL[extConfig]['.$k.']['.$vk.']',
  1839. 'value' => str_replace(array("'.chr(10).'", "' . LF . '"), array(LF, LF), $value)
  1840. );
  1841. $value = str_replace(array("'.chr(10).'", "' . LF . '"), array(' | ', ' | '), $value);
  1842. // Fill the markers in the subpart
  1843. $textAreaSubpart = t3lib_parsehtml::substituteMarkerArray(
  1844. $textAreaSubpart,
  1845. $textAreaMarkers,
  1846. '###|###',
  1847. TRUE,
  1848. FALSE
  1849. );
  1850. } elseif (preg_match('/^(<.*?>)?boolean/i', $description)) {
  1851. // Get the subpart for a checkbox
  1852. $booleanSubpart = t3lib_parsehtml::getSubpart($template, '###BOOLEAN###');
  1853. // Define the markers content
  1854. $booleanMarkers = array(
  1855. 'id' => $k . '-' . $vk,
  1856. 'name' => 'TYPO3_INSTALL[extConfig]['.$k.']['.$vk.']',
  1857. 'value' => $value && strcmp($value, '0') ? $value : 1,
  1858. 'checked' => $value ? 'checked="checked"' : ''
  1859. );
  1860. // Fill the markers in the subpart
  1861. $booleanSubpart = t3lib_parsehtml::substituteMarkerArray(
  1862. $booleanSubpart,
  1863. $booleanMarkers,
  1864. '###|###',
  1865. TRUE,
  1866. FALSE
  1867. );
  1868. } else {
  1869. // Get the subpart for an input text field
  1870. $textLineSubpart = t3lib_parsehtml::getSubpart($template, '###TEXTLINE###');
  1871. // Define the markers content
  1872. $textLineMarkers = array(
  1873. 'id' => $k . '-' . $vk,
  1874. 'name' => 'TYPO3_INSTALL[extConfig]['.$k.']['.$vk.']',
  1875. 'value' => $value
  1876. );
  1877. // Fill the markers in the subpart
  1878. $textLineSubpart = t3lib_parsehtml::substituteMarkerArray(
  1879. $textLineSubpart,
  1880. $textLineMarkers,
  1881. '###|###',
  1882. TRUE,
  1883. FALSE
  1884. );
  1885. }
  1886. // Substitute the subpart for a textarea
  1887. $content = t3lib_parsehtml::substituteSubpart(
  1888. $template,
  1889. '###TEXTAREA###',
  1890. $textAreaSubpart
  1891. );
  1892. // Substitute the subpart for a checkbox
  1893. $content = t3lib_parsehtml::substituteSubpart(
  1894. $content,
  1895. '###BOOLEAN###',
  1896. $booleanSubpart
  1897. );
  1898. // Substitute the subpart for an input text field
  1899. $content = t3lib_parsehtml::substituteSubpart(
  1900. $content,
  1901. '###TEXTLINE###',
  1902. $textLineSubpart
  1903. );
  1904. // Define the markers content
  1905. $markers = array(
  1906. 'description' => $description,
  1907. 'key' => '[' . $k . '][' . $vk . ']',
  1908. 'label' => htmlspecialchars(t3lib_div::fixed_lgd_cs($value, 40))
  1909. );
  1910. // Fill the markers
  1911. $content = t3lib_parsehtml::substituteMarkerArray(
  1912. $content,
  1913. $markers,
  1914. '###|###',
  1915. TRUE,
  1916. FALSE
  1917. );
  1918. // Add the content to the message array
  1919. $this->message($ext, $k2, $content);
  1920. }
  1921. }
  1922. }
  1923. break;
  1924. default:
  1925. if (is_array($this->INSTALL['extConfig'])) {
  1926. $lines = $this->writeToLocalconf_control();
  1927. foreach ($this->INSTALL['extConfig'] as $k => $va) {
  1928. if (is_array($GLOBALS['TYPO3_CONF_VARS'][$k])) {
  1929. foreach ($va as $vk => $value) {
  1930. if (isset($GLOBALS['TYPO3_CONF_VARS'][$k][$vk])) {
  1931. $doit=1;
  1932. if ($k=='BE' && $vk=='installToolPassword') {
  1933. if ($value) {
  1934. if (isset($_POST['installToolPassword_check'])) {
  1935. if (!$this->formProtection->validateToken(
  1936. (string) $_POST['formToken'],
  1937. 'installToolPassword',
  1938. 'change'
  1939. )) {
  1940. $doit = FALSE;
  1941. break;
  1942. }
  1943. if (!t3lib_div::_GP('installToolPassword_check')
  1944. || strcmp(t3lib_div::_GP('installToolPassword_check'), $value)
  1945. ) {
  1946. $doit = FALSE;
  1947. $this->errorMessages[]
  1948. = 'The two passwords did not ' .
  1949. 'match! The password was not changed.';
  1950. }
  1951. }
  1952. if (t3lib_div::_GP('installToolPassword_md5')) $value =md5($value);
  1953. } else $doit=0;
  1954. }
  1955. $description = trim($commentArr[1][$k][$vk]);
  1956. if (preg_match('/^string \(textarea\)/i', $description)) {
  1957. // Force Unix linebreaks in textareas
  1958. $value = str_replace(CR, '', $value);
  1959. // Preserve linebreaks
  1960. $value = str_replace(LF, "' . LF . '", $value);
  1961. }
  1962. if (preg_match('/^boolean/i', $description)) {
  1963. // When submitting settings in the Install Tool, values that default to "FALSE" or "true"
  1964. // in t3lib/stddb/DefaultSettings.php will be sent as "0" resp. "1". Therefore, reset the values
  1965. // to their boolean equivalent.
  1966. if ($GLOBALS['TYPO3_CONF_VARS'][$k][$vk] === FALSE && $value === '0') {
  1967. $value = FALSE;
  1968. } elseif ($GLOBALS['TYPO3_CONF_VARS'][$k][$vk] === TRUE && $value === '1') {
  1969. $value = TRUE;
  1970. }
  1971. }
  1972. if ($doit && strcmp($GLOBALS['TYPO3_CONF_VARS'][$k][$vk], $value)) $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\''.$k.'\'][\''.$vk.'\']', $value);
  1973. }
  1974. }
  1975. }
  1976. }
  1977. $this->writeToLocalconf_control($lines);
  1978. }
  1979. break;
  1980. }
  1981. }
  1982. /**
  1983. * Make an array of the comments in the t3lib/stddb/DefaultSettings.php file
  1984. *
  1985. * @param string $string The contents of the t3lib/stddb/DefaultSettings.php file
  1986. * @param array $mainArray
  1987. * @param array $commentArray
  1988. * @return array
  1989. */
  1990. function getDefaultConfigArrayComments($string, $mainArray=array(), $commentArray=array()) {
  1991. $lines = explode(LF, $string);
  1992. $in=0;
  1993. $mainKey='';
  1994. foreach ($lines as $lc) {
  1995. $lc = trim($lc);
  1996. if ($in) {
  1997. if (!strcmp($lc, ');')) {
  1998. $in=0;
  1999. } else {
  2000. if (preg_match('/["\']([[:alnum:]_-]*)["\'][[:space:]]*=>(.*)/i', $lc, $reg)) {
  2001. preg_match('/,[\t\s]*\/\/(.*)/i', $reg[2], $creg);
  2002. $theComment = trim($creg[1]);
  2003. if (substr(strtolower(trim($reg[2])), 0, 5)=='array' && !strcmp($reg[1], strtoupper($reg[1]))) {
  2004. $mainKey=trim($reg[1]);
  2005. $mainArray[$mainKey]=$theComment;
  2006. } elseif ($mainKey) {
  2007. $commentArray[$mainKey][$reg[1]]=$theComment;
  2008. }
  2009. }
  2010. }
  2011. }
  2012. if (!strcmp($lc, 'return array(')) {
  2013. $in=1;
  2014. }
  2015. }
  2016. return array($mainArray, $commentArray);
  2017. }
  2018. /*******************************
  2019. *
  2020. * CHECK CONFIGURATION FUNCTIONS
  2021. *
  2022. *******************************/
  2023. /**
  2024. * Checking php.ini configuration and set appropriate messages and flags.
  2025. *
  2026. * @return void
  2027. */
  2028. function checkConfiguration() {
  2029. $ext='php.ini configuration checked';
  2030. $this->message($ext);
  2031. // *****************
  2032. // Incoming values:
  2033. // *****************
  2034. // Includepath
  2035. $incPaths = t3lib_div::trimExplode(TYPO3_OS=='WIN'?';':':', ini_get('include_path'));
  2036. if (!in_array('.', $incPaths)) {
  2037. $this->message($ext, 'Current directory (./) is not in include path!', '
  2038. <p>
  2039. <em>include_path=' . ini_get('include_path') . '</em>
  2040. <br />
  2041. Normally the current path, \'.\', is included in the
  2042. include_path of PHP. Although TYPO3 does not rely on this,
  2043. it is an unusual setting that may introduce problems for
  2044. some extensions.
  2045. </p>
  2046. ', 1);
  2047. } else $this->message($ext, 'Current directory in include path', '', -1);
  2048. // *****************
  2049. // File uploads
  2050. // *****************
  2051. if (!ini_get('file_uploads')) {
  2052. $this->message($ext, 'File uploads not allowed', '
  2053. <p>
  2054. <em>file_uploads=' . ini_get('file_uploads') . '</em>
  2055. <br />
  2056. TYPO3 uses the ability to upload files from the browser in
  2057. various cases.
  2058. <br />
  2059. As long as this flag is disabled, you\'ll not be able to
  2060. upload files.
  2061. <br />
  2062. But it doesn\'t end here, because not only are files not
  2063. accepted by the server - ALL content in the forms are
  2064. discarded and therefore nothing at all will be editable
  2065. if you don\'t set this flag!
  2066. <br />
  2067. However if you cannot enable fileupload for some reason
  2068. alternatively you change the default form encoding value
  2069. with \$TYPO3_CONF_VARS[SYS][form_enctype].
  2070. </p>
  2071. ', 3);
  2072. } else $this->message($ext, 'File uploads allowed', '', -1);
  2073. $upload_max_filesize = t3lib_div::getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
  2074. $post_max_size = t3lib_div::getBytesFromSizeMeasurement(ini_get('post_max_size'));
  2075. if ($upload_max_filesize<1024*1024*10) {
  2076. $this->message($ext, 'Maximum upload filesize too small?', '
  2077. <p>
  2078. <em>upload_max_filesize=' . ini_get('upload_max_filesize') . '</em>
  2079. <br />
  2080. By default TYPO3 supports uploading, copying and moving
  2081. files of sizes up to 10MB (You can alter the TYPO3 defaults
  2082. by the config option TYPO3_CONF_VARS[BE][maxFileSize]).
  2083. <br />
  2084. Your current value is below this, so at this point, PHP sets
  2085. the limits for uploaded filesizes and not TYPO3.
  2086. <br />
  2087. <strong>Notice:</strong> The limits for filesizes attached
  2088. to database records are set in the tables.php configuration
  2089. files (\$TCA) for each group/file field. You may override
  2090. these values in localconf.php or by page TSconfig settings.
  2091. </p>
  2092. ', 1);
  2093. }
  2094. if ($upload_max_filesize > $post_max_size) {
  2095. $this->message($ext, 'Maximum size for POST requests is smaller than max. upload filesize', '
  2096. <p>
  2097. <em>upload_max_filesize=' . ini_get('upload_max_filesize') . '
  2098. , post_max_size=' . ini_get('post_max_size') . '</em>
  2099. <br />
  2100. You have defined a maximum size for file uploads which
  2101. exceeds the allowed size for POST requests. Therefore the
  2102. file uploads can not be larger than ' . ini_get('post_max_size') . '
  2103. </p>
  2104. ', 1);
  2105. }
  2106. // *****************
  2107. // Memory and functions
  2108. // *****************
  2109. $memory_limit_value = t3lib_div::getBytesFromSizeMeasurement(ini_get('memory_limit'));
  2110. if ($memory_limit_value <= 0) {
  2111. $this->message(
  2112. $ext,
  2113. 'Unlimited memory limit!',
  2114. '<p>Your webserver is configured to not limit PHP memory usage at all. This is a risk
  2115. and should be avoided in production setup. In general it\'s best practice to limit this
  2116. in the configuration of your webserver. To be safe, ask the system administrator of the
  2117. webserver to raise the limit to something over ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT .
  2118. '.</p>',
  2119. 2
  2120. );
  2121. } elseif ($memory_limit_value < t3lib_div::getBytesFromSizeMeasurement(TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT)) {
  2122. $this->message($ext, 'Memory limit below ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT, '
  2123. <p>
  2124. <em>memory_limit=' . ini_get('memory_limit') . '</em>
  2125. <br />
  2126. Your system is configured to enforce a memory limit of PHP
  2127. scripts lower than ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT . '.
  2128. The Extension Manager needs to include more PHP-classes than
  2129. will fit into this memory space. There is nothing else to do
  2130. than raise the limit. To be safe, ask the system
  2131. administrator of the webserver to raise the limit to over
  2132. ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT . '.
  2133. </p>
  2134. ', 3);
  2135. } else {
  2136. $this->message($ext, 'Memory limit: ' . ini_get('memory_limit'), '', -1);
  2137. }
  2138. if (ini_get('max_execution_time')<30) {
  2139. $this->message($ext, 'Maximum execution time below 30 seconds', '
  2140. <p>
  2141. <em>max_execution_time=' . ini_get('max_execution_time') . '</em>
  2142. <br />
  2143. May impose problems if too low.
  2144. </p>
  2145. ', 1);
  2146. } else {
  2147. $this->message($ext, 'Maximum execution time: ' . ini_get('max_execution_time') . ' seconds', '', -1);
  2148. }
  2149. if (ini_get('disable_functions')) {
  2150. $this->message($ext, 'Functions disabled!', '
  2151. <p>
  2152. <em>disable_functions=' . ini_get('disable_functions') . '</em>
  2153. <br />
  2154. The above list of functions are disabled. If TYPO3 use any
  2155. of these there might be trouble.
  2156. <br />
  2157. TYPO3 is designed to use the default set of PHP4.3.0+
  2158. functions plus the functions of GDLib.
  2159. <br />
  2160. Possibly these functions are disabled due to security risks
  2161. and most likely the list would include a function like
  2162. <em>exec()</em> which is use by TYPO3 to access ImageMagick.
  2163. </p>
  2164. ', 2);
  2165. } else {
  2166. $this->message($ext, 'Functions disabled: none', '', -1);
  2167. }
  2168. // Mail tests
  2169. if (TYPO3_OS == 'WIN') {
  2170. $smtp = ini_get('SMTP');
  2171. $bad_smtp = FALSE;
  2172. if (!t3lib_div::validIP($smtp)) {
  2173. $smtp_addr = @gethostbyname($smtp);
  2174. $bad_smtp = ($smtp_addr == $smtp);
  2175. }
  2176. else {
  2177. $smtp_addr = $smtp;
  2178. }
  2179. if (!$smtp || $bad_smtp || !t3lib_utility_Math::canBeInterpretedAsInteger(ini_get('smtp_port'))) {
  2180. $this->message($ext, 'Mail configuration is not set correctly', '
  2181. <p>
  2182. Mail configuration is not set
  2183. <br />
  2184. PHP mail() function requires SMTP and smtp_port to have
  2185. correct values on Windows.
  2186. </p>
  2187. ', 2);
  2188. } else {
  2189. if (($smtp_addr == '127.0.0.1' || $smtp_addr == '::1') && ($_SERVER['SERVER_ADDR'] == '127.0.0.1' || $_SERVER['SERVER_ADDR'] == '::1')) {
  2190. $this->message($ext, 'Mail is configured (potential problem exists!)', '
  2191. <p>
  2192. <em>SMTP=' . $smtp . '</em> - <strong>Note:</strong>
  2193. this server! Are you sure it runs SMTP server?
  2194. <br />
  2195. <em>smtp_port=' . ini_get('smtp_port') . '</em>
  2196. </p>' . $this->check_mail('get_form') . '
  2197. ', 1);
  2198. } else {
  2199. $this->message($ext, 'Mail is configured', '
  2200. <p>
  2201. <em>SMTP=' . $smtp . '</em>
  2202. <br />
  2203. <em>smtp_port=' . ini_get('smtp_port') . '</em>
  2204. </p>' . $this->check_mail('get_form') .'
  2205. ', -1);
  2206. }
  2207. }
  2208. } elseif (!ini_get('sendmail_path')) {
  2209. $this->message($ext, 'Sendmail path not defined!', '
  2210. <p>
  2211. This may be critical to TYPO3\'s use of the mail() function.
  2212. Please be sure that the mail() function in your
  2213. php-installation works!
  2214. </p>' . $this->check_mail('get_form') . '
  2215. ', 1);
  2216. } else {
  2217. list($prg) = explode(' ', ini_get('sendmail_path'));
  2218. if (!@is_executable($prg)) {
  2219. $this->message($ext, 'Sendmail program not found or not executable?', '
  2220. <p>
  2221. <em>sendmail_path=' . ini_get('sendmail_path') . '</em>
  2222. <br />
  2223. This may be critical to TYPO3\'s use of the mail()
  2224. function. Please be sure that the mail() function in
  2225. your php-installation works!
  2226. </p>' . $this->check_mail('get_form') .'
  2227. ', 1);
  2228. } else {
  2229. $this->message($ext, 'Sendmail OK', '
  2230. <p>
  2231. <em>sendmail_path=' . ini_get('sendmail_path') . '</em>
  2232. </p>' . $this->check_mail('get_form') . '
  2233. ', -1);
  2234. }
  2235. }
  2236. // *****************
  2237. // Safe mode related
  2238. // *****************
  2239. if (t3lib_utility_PhpOptions::isSafeModeEnabled()) {
  2240. $this->message($ext, 'Safe mode turned on', '
  2241. <p>
  2242. <em>safe_mode=' . ini_get('safe_mode') . '</em>
  2243. <br />
  2244. In safe_mode PHP is restricted in several ways. This is a
  2245. good thing because it adds protection to your (and others)
  2246. scripts. But it may also introduce problems. In TYPO3 this
  2247. <em>may be</em> a problem in two areas: File administration
  2248. and execution of external programs, in particular
  2249. ImageMagick.
  2250. <br />
  2251. If you just ignore this warning, you\'ll most likely find,
  2252. that TYPO3 seems to work except from the image-generation.
  2253. The problem in that case is that the external ImageMagick
  2254. programs are not allowed to be executed from the regular
  2255. paths like "/usr/bin/" or "/usr/X11R6/bin/".
  2256. <br />
  2257. If you use safe_mode with TYPO3, you should disable use of
  2258. external programs ([BE][disable_exec_function]=1).
  2259. <br />
  2260. In safe mode you must ensure that all the php-scripts and
  2261. upload folders are owned by the same user.
  2262. </p>
  2263. <p>
  2264. <em>safe_mode_exec_dir=' . ini_get('safe_mode_exec_dir') . '</em>
  2265. <br />
  2266. If the ImageMagick utilities are located in this directory,
  2267. everything is fine. Below on this page, you can see if
  2268. ImageMagick is found here. If not, ask you ISP to put the
  2269. three ImageMagick programs, \'convert\',
  2270. \'combine\'/\'composite\' and \'identify\' there (eg. with
  2271. symlinks if Unix server)
  2272. </p>
  2273. <p>
  2274. <strong>Example of safe_mode settings:</strong>
  2275. <br />
  2276. Set this in the php.ini file:
  2277. </p>
  2278. <p>
  2279. ; Safe Mode
  2280. <br />
  2281. safe_mode = On
  2282. <br />
  2283. safe_mode_exec_dir = /usr/bin/
  2284. </p>
  2285. <p>
  2286. ...and the ImageMagick \'/usr/bin/convert\' will be
  2287. executable.
  2288. <br />
  2289. The last slash is important (..../) and you can only specify
  2290. one directory.
  2291. </p>
  2292. <p>
  2293. <strong>Notice: </strong>
  2294. <br />
  2295. ImageMagick 6 or GraphicsMagick is recommended and the binaries are
  2296. normally installed in /usr/bin.
  2297. <br />
  2298. Paths to ImageMagick are defined in localconf.php and may be
  2299. something else than /usr/bin/, but this is default for
  2300. ImageMagick 6+
  2301. </p>
  2302. ', 2);
  2303. if (ini_get('doc_root')) {
  2304. $this->message($ext, 'doc_root set', '
  2305. <p>
  2306. <em>doc_root=' . ini_get('doc_root') . '</em>
  2307. <br />
  2308. PHP cannot execute scripts outside this directory. If
  2309. that is a problem is please correct it.
  2310. </p>
  2311. ', 1);
  2312. }
  2313. $this->config_array['safemode']=1;
  2314. } else {
  2315. $this->message($ext, 'safe_mode: off', '', -1);
  2316. }
  2317. if (t3lib_utility_PhpOptions::isSqlSafeModeEnabled()) {
  2318. $this->message($ext, 'sql.safe_mode is enabled', '
  2319. <p>
  2320. <em>sql.safe_mode=' . ini_get('sql.safe_mode') . '</em>
  2321. <br />
  2322. This means that you can only connect to the database with a
  2323. username corresponding to the user of the webserver process
  2324. or fileowner. Consult your ISP for information about this.
  2325. Also see <a href="http://www.wrox.com/Consumer/Store/Books/2963/29632002.htm">
  2326. http://www.wrox.com/Consumer/Store/Books/2963/29632002.htm</a>
  2327. <br />
  2328. The owner of the current file is:
  2329. <strong>' . get_current_user () . '</strong>
  2330. </p>
  2331. ', 1);
  2332. $this->config_array['sql.safe_mode_user'] = get_current_user();
  2333. } else {
  2334. $this->message($ext, 'sql.safe_mode: off', '', -1);
  2335. }
  2336. if (ini_get('open_basedir')) {
  2337. $this->message($ext, 'open_basedir set', '
  2338. <p>
  2339. <em>open_basedir=' . ini_get('open_basedir') . '</em>
  2340. <br />
  2341. This restricts TYPO3 to open and include files only in this
  2342. path. Please make sure that this does not prevent TYPO3 from
  2343. running.
  2344. <br />
  2345. <strong>Notice (UNIX):</strong> Before checking a path
  2346. according to open_basedir, PHP resolves all symbolic links.
  2347. </p>
  2348. ', 1);
  2349. // ???? If this option was set falsely you probably didn't see this page in the
  2350. // first place, but this option <strong>may spoil this configuration test</strong>
  2351. // when checking for such as ImageMagick executables.
  2352. } else {
  2353. $this->message($ext, 'open_basedir: off', '', -1);
  2354. }
  2355. // Check availability of PHP session support
  2356. if (extension_loaded('session')) {
  2357. $this->message($ext, 'PHP sessions available', '
  2358. <p>
  2359. <em>PHP Sessions available</em>
  2360. <br />
  2361. PHP is compiled with session support and session support is
  2362. available.
  2363. </p>
  2364. ', -1);
  2365. } else {
  2366. $this->message($ext, 'PHP Sessions not available', '
  2367. <p>
  2368. PHP is not compiled with session support, or session support
  2369. is disabled in php.ini.
  2370. <br />
  2371. TYPO3 needs session support.
  2372. </p>
  2373. ', 3);
  2374. }
  2375. // Suhosin/Hardened PHP:
  2376. $suhosinDescription = '
  2377. <p>
  2378. Suhosin limits the number of elements that can be submitted in
  2379. forms to the server. This will affect for example the
  2380. "All configuration" section in the Install Tool or Inline
  2381. Relational Record Editing (IRRE) with many child records.
  2382. </p>';
  2383. if (extension_loaded('suhosin')) {
  2384. $suhosinSuggestion = '
  2385. <p>
  2386. At least a value of 400 is suggested.
  2387. </p>
  2388. ';
  2389. $suhosinRequestMaxVars = ini_get('suhosin.request.max_vars');
  2390. $suhosinPostMaxVars = ini_get('suhosin.post.max_vars');
  2391. $suhosinRequestMaxVarsType = ($suhosinRequestMaxVars < 400 ? 2 : -1);
  2392. $suhosinPostMaxVarsType = ($suhosinPostMaxVars < 400 ? 2 : -1);
  2393. $suhosinType = ($suhosinRequestMaxVars < 400 || $suhosinPostMaxVars < 400 ? 2 : -1);
  2394. $this->message($ext, 'Suhosin/Hardened PHP is loaded', $suhosinDescription, $suhosinType);
  2395. $this->message($ext, 'suhosin.request.max_vars: ' . $suhosinRequestMaxVars, $suhosinSuggestion, $suhosinRequestMaxVarsType);
  2396. $this->message($ext, 'suhosin.post.max_vars: ' . $suhosinPostMaxVars, $suhosinSuggestion, $suhosinPostMaxVarsType);
  2397. } else {
  2398. $this->message($ext, 'Suhosin/Hardened PHP is not loaded', $suhosinDescription, 0);
  2399. }
  2400. // Check for stripped PHPdoc comments that are required to evaluate annotations:
  2401. $method = new ReflectionMethod('tx_install', 'check_mail');
  2402. if (strlen($method->getDocComment()) === 0) {
  2403. $description = '
  2404. <p>
  2405. The system extension Extbase evaluates annotations in PHPdoc
  2406. comments and thus requires eAccelerator not to strip away
  2407. these parts. However, this is currently the only part in the
  2408. TYPO3 Core (beside deprecation log and unit tests). If
  2409. Extbase is not used, recompiling eAccelerator is not
  2410. required at all.
  2411. <br/>
  2412. <br/>
  2413. If you do not want comments to be stripped by eAccelerator,
  2414. please recompile with the following configuration setting
  2415. (<a href="http://eaccelerator.net/ticket/229" target="_blank">
  2416. more details</a>):
  2417. <br />
  2418. <em>--with-eaccelerator-doc-comment-inclusion</em>
  2419. </p>
  2420. ';
  2421. $this->message($ext, 'PHPdoc comments are stripped', $description, 2);
  2422. }
  2423. }
  2424. /**
  2425. * Check if PHP function mail() works
  2426. *
  2427. * @param string $cmd If "get_form" then a formfield for the mail-address is shown. If not, it's checked if "check_mail" was in the INSTALL array and if so a test mail is sent to the recipient given.
  2428. * @return string The mail form if it is requested with get_form
  2429. */
  2430. function check_mail($cmd='') {
  2431. switch($cmd) {
  2432. case 'get_form':
  2433. $out = '
  2434. <p id="checkMailForm">
  2435. You can check the t3lib_mail functionality by entering your email
  2436. address here and press the button. You should then
  2437. receive a testmail from "typo3installtool@example.org".
  2438. </p>
  2439. ';
  2440. // Get the template file
  2441. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckMail.html');
  2442. // Get the template part from the file
  2443. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  2444. if (!empty($this->mailMessage)) {
  2445. // Get the subpart for the mail is sent message
  2446. $mailSentSubpart = t3lib_parsehtml::getSubpart($template, '###MAILSENT###');
  2447. }
  2448. // Substitute the subpart for the mail is sent message
  2449. $template = t3lib_parsehtml::substituteSubpart(
  2450. $template,
  2451. '###MAILSENT###',
  2452. $mailSentSubpart
  2453. );
  2454. // Define the markers content
  2455. $markers = array(
  2456. 'message' => $this->mailMessage,
  2457. 'enterEmail' => 'Enter the email address',
  2458. 'actionUrl' => $this->action . '#checkMailForm',
  2459. 'submit' => 'Send test mail'
  2460. );
  2461. // Fill the markers
  2462. $out .= t3lib_parsehtml::substituteMarkerArray(
  2463. $template,
  2464. $markers,
  2465. '###|###',
  2466. TRUE,
  2467. TRUE
  2468. );
  2469. break;
  2470. default:
  2471. if (trim($this->INSTALL['check_mail'])) {
  2472. $subject = 'TEST SUBJECT';
  2473. $email = trim($this->INSTALL['check_mail']);
  2474. /** @var $mailMessage t3lib_mail_Message */
  2475. $mailMessage = t3lib_div::makeInstance('t3lib_mail_Message');
  2476. $mailMessage->addTo($email)
  2477. ->addFrom('typo3installtool@example.org', 'TYPO3 Install Tool')
  2478. ->setSubject($subject)
  2479. ->setBody('<html><body>HTML TEST CONTENT</body></html>');
  2480. $mailMessage->addPart('TEST CONTENT');
  2481. $mailMessage->send();
  2482. $this->mailMessage= 'Mail was sent to: ' . $email;
  2483. }
  2484. break;
  2485. }
  2486. return $out;
  2487. }
  2488. /**
  2489. * Checking php extensions, specifically GDLib and Freetype
  2490. *
  2491. * @return void
  2492. */
  2493. function checkExtensions() {
  2494. $ext = 'GDLib';
  2495. $this->message($ext);
  2496. $software_info=1;
  2497. if (extension_loaded('gd') && $this->isGD()) {
  2498. $this->config_array['gd']=1;
  2499. $this->message($ext, 'GDLib found', '', -1);
  2500. if ($this->isPNG()) {
  2501. $this->config_array['gd_png']=1;
  2502. $this->message($ext, 'PNG supported', '', -1);
  2503. }
  2504. if ($this->isGIF()) {
  2505. $this->config_array['gd_gif']=1;
  2506. $this->message($ext, 'GIF supported', '', -1);
  2507. }
  2508. if ($this->isJPG()) {
  2509. $this->config_array['gd_jpg']=1;
  2510. $this->message($ext, 'JPG supported (not used by TYPO3)', '');
  2511. }
  2512. if (!$this->config_array['gd_gif'] && !$this->config_array['gd_png']) {
  2513. $this->message($ext, 'PNG or GIF not supported', '
  2514. <p>
  2515. Your GDLib supports either GIF nor PNG. It must support
  2516. either one of them.
  2517. </p>
  2518. ', 2);
  2519. } else {
  2520. $msg=array();
  2521. if ($this->config_array['gd_gif'] && $this->config_array['gd_png']) {
  2522. $msg[] = '
  2523. <p>
  2524. You can choose between generating GIF or PNG files,
  2525. as your GDLib supports both.
  2526. </p>
  2527. ';
  2528. }
  2529. if ($this->config_array['gd_gif']) {
  2530. $msg[] = '
  2531. <p>
  2532. You should watch out for the generated size of the
  2533. GIF-files because some versions of the GD library do
  2534. not compress them with LZW, but RLE and ImageMagick
  2535. is subsequently used to compress with LZW. But in
  2536. the case of ImageMagick failing this task (eg. not
  2537. being compiled with LZW which is the case with some
  2538. versions) you\'ll end up with GIF-filesizes all too
  2539. big!
  2540. <br />
  2541. This Install Tool tests what kinds of GIF
  2542. compression are available in the ImageMagick
  2543. installations by a physical test. You can also check
  2544. it manually by opening a TYPO3 generated gif-file
  2545. with Photoshop and save it in a new file. If the
  2546. file sizes of the original and the new file are
  2547. almost the same, you\'re having LZW compression and
  2548. everything is fine.
  2549. </p>
  2550. ';
  2551. }
  2552. if ($this->config_array['gd_png']) {
  2553. $msg[] = '
  2554. <p>
  2555. TYPO3 prefers the use of GIF-files and most likely
  2556. your visitors on your website does too as not all
  2557. browsers support PNG yet.
  2558. </p>
  2559. ';
  2560. }
  2561. $this->message($ext, 'GIF / PNG issues', implode(LF, $msg), 1);
  2562. }
  2563. if (!$this->isTTF()) {
  2564. $this->message($ext, 'FreeType is apparently not installed', '
  2565. <p>
  2566. It looks like the FreeType library is not compiled into
  2567. GDLib. This is required when TYPO3 uses GDLib and
  2568. you\'ll most likely get errors like \'ImageTTFBBox is
  2569. not a function\' or \'ImageTTFText is not a function\'.
  2570. </p>
  2571. ', 2);
  2572. } else {
  2573. $this->message($ext, 'FreeType quick-test (' . ($this->isGIF() ? 'as GIF' : 'as PNG') . ')', '
  2574. <p>
  2575. <img src="' . htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI') . '&testingTrueTypeSupport=1') . '" alt="" />
  2576. <br />
  2577. (If the text is exceeding the image borders you are
  2578. using Freetype 2 and need to set
  2579. TYPO3_CONF_VARS[GFX][TTFdpi]=96.
  2580. <br />
  2581. If there is no image at all Freetype is most likely NOT
  2582. available and you can just as well disable GDlib for
  2583. TYPO3...)
  2584. </p>
  2585. ', -1);
  2586. $this->config_array['freetype']=1;
  2587. }
  2588. } else {
  2589. $this->message($ext, 'GDLib2 not found', '
  2590. <p>
  2591. GDLib2 is required if you want to use the GIFBUILDER object
  2592. in TypoScript. GIFBUILDER is in charge of all advanced image
  2593. generation in TypoScript, including graphical menuitems.
  2594. <br />
  2595. GDLib2 is also used in the TYPO3 Backend (TBE) to generate
  2596. record icons and new module tabs.
  2597. <br />
  2598. It\'s highly recommended to install this library. Remember
  2599. to compile GD with FreeType which is also required.
  2600. <br />
  2601. If you choose not to install GDLib, you can disable it in
  2602. the configuration with [GFX][gdlib]=0;.
  2603. </p>
  2604. ', 2);
  2605. }
  2606. $this->message($ext, 'GDLib software information', $this->getGDSoftwareInfo());
  2607. }
  2608. /**
  2609. * Checking and testing that the required writable directories are writable.
  2610. *
  2611. * @return void
  2612. */
  2613. function checkDirs() {
  2614. // Check typo3/temp/
  2615. $ext='Directories';
  2616. $this->message($ext);
  2617. $uniqueName = md5(uniqid(microtime()));
  2618. // The requirement level (the integer value, ie. the second value of the value array) has the following meanings:
  2619. // -1 = not required, but if it exists may be writable or not
  2620. // 0 = not required, if it exists the dir should be writable
  2621. // 1 = required, don't has to be writable
  2622. // 2 = required, has to be writable
  2623. $checkWrite=array(
  2624. 'typo3temp/' => array('This folder is used by both the frontend (FE) and backend (BE) interface for all kind of temporary and cached files.', 2, 'dir_typo3temp'),
  2625. 'typo3temp/pics/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
  2626. 'typo3temp/temp/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
  2627. 'typo3temp/llxml/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
  2628. 'typo3temp/cs/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
  2629. 'typo3temp/GB/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
  2630. 'typo3temp/locks/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
  2631. 'typo3conf/' => array('This directory contains the local configuration files of your website. TYPO3 must be able to write to these configuration files during setup and when the Extension Manager (EM) installs extensions.', 2),
  2632. 'typo3conf/ext/' => array('Location for local extensions. Must be writable if the Extension Manager is supposed to install extensions for this website.', 0),
  2633. 'typo3conf/l10n/' => array('Location for translations. Must be writable if the Extension Manager is supposed to install translations for extensions.', 0),
  2634. TYPO3_mainDir.'ext/' => array('Location for global extensions. Must be writable if the Extension Manager is supposed to install extensions globally in the source.', -1),
  2635. 'uploads/' => array('Location for uploaded files from RTE, in the subdirectories for uploaded files of content elements.', 2),
  2636. 'uploads/pics/' => array('Typical location for uploaded files (images especially).', 0),
  2637. 'uploads/media/' => array('Typical location for uploaded files (non-images especially).', 0),
  2638. 'uploads/tf/' => array('Typical location for uploaded files (TS template resources).', 0),
  2639. $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] => array('Location for local files such as templates, independent uploads etc.', -1),
  2640. $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/' => array('Typical temporary location for default upload of files by administrators.', 0),
  2641. );
  2642. foreach ($checkWrite as $relpath => $descr) {
  2643. // Check typo3temp/
  2644. $general_message = $descr[0];
  2645. // If the directory is missing, try to create it
  2646. if (!@is_dir(PATH_site.$relpath)) {
  2647. t3lib_div::mkdir(PATH_site.$relpath);
  2648. }
  2649. if (!@is_dir(PATH_site.$relpath)) {
  2650. if ($descr[1]) { // required...
  2651. $this->message($ext, $relpath.' directory does not exist and could not be created', '
  2652. <p>
  2653. <em>Full path: ' . PATH_site . $relpath . '</em>
  2654. <br />
  2655. ' . $general_message . '
  2656. </p>
  2657. <p>
  2658. This error should not occur as ' . $relpath . ' must
  2659. always be accessible in the root of a TYPO3 website.
  2660. </p>
  2661. ', 3);
  2662. } else {
  2663. if ($descr[1] == 0) {
  2664. $msg = 'This directory does not necessarily have to exist but if it does it must be writable.';
  2665. } else {
  2666. $msg = 'This directory does not necessarily have to exist and if it does it can be writable or not.';
  2667. }
  2668. $this->message($ext, $relpath.' directory does not exist', '
  2669. <p>
  2670. <em>Full path: ' . PATH_site . $relpath . '</em>
  2671. <br />
  2672. ' . $general_message . '
  2673. </p>
  2674. <p>
  2675. ' . $msg . '
  2676. </p>
  2677. ', 2);
  2678. }
  2679. } else {
  2680. $file = PATH_site.$relpath.$uniqueName;
  2681. @touch($file);
  2682. if (@is_file($file)) {
  2683. unlink($file);
  2684. if ($descr[2]) { $this->config_array[$descr[2]]=1; }
  2685. $this->message($ext, $relpath.' writable', '', -1);
  2686. } else {
  2687. $severity = ($descr[1]==2 || $descr[1]==0) ? 3 : 2;
  2688. if ($descr[1] == 0 || $descr[1] == 2) {
  2689. $msg = 'The directory '.$relpath.' must be writable!';
  2690. } elseif ($descr[1] == -1 || $descr[1] == 1) {
  2691. $msg = 'The directory '.$relpath.' does not neccesarily have to be writable.';
  2692. }
  2693. $this->message($ext, $relpath .' directory not writable', '
  2694. <p>
  2695. <em>Full path: ' . $file . '</em>
  2696. <br />
  2697. ' . $general_message . '
  2698. </p>
  2699. <p>
  2700. Tried to write this file (with touch()) but didn\'t
  2701. succeed.
  2702. <br />
  2703. ' . $msg . '
  2704. </p>
  2705. ', $severity);
  2706. }
  2707. }
  2708. }
  2709. }
  2710. /**
  2711. * Checking for existing ImageMagick installs.
  2712. *
  2713. * This tries to find available ImageMagick installations and tries to find the version numbers by executing "convert" without parameters. If the ->checkIMlzw is set, LZW capabilities of the IM installs are check also.
  2714. *
  2715. * @param array $paths Possible ImageMagick paths
  2716. * @return void
  2717. */
  2718. function checkImageMagick($paths) {
  2719. $ext='Check Image Magick';
  2720. $this->message($ext);
  2721. // Get the template file
  2722. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckImageMagick.html');
  2723. $paths = array_unique($paths);
  2724. $programs = explode(',', 'gm,convert,combine,composite,identify');
  2725. $isExt = TYPO3_OS=='WIN' ? '.exe' : '';
  2726. $this->config_array['im_combine_filename']='combine';
  2727. foreach ($paths as $k => $v) {
  2728. if (!preg_match('/[\\/]$/', $v)) $v.='/';
  2729. foreach ($programs as $filename) {
  2730. if (ini_get('open_basedir') || (file_exists($v) && @is_file($v.$filename.$isExt))) {
  2731. $version = $this->_checkImageMagick_getVersion($filename, $v);
  2732. if($version > 0) {
  2733. // Assume GraphicsMagick
  2734. if($filename=='gm') {
  2735. $index[$v]['gm']=$version;
  2736. // No need to check for "identify" etc.
  2737. continue;
  2738. } else {
  2739. // Assume ImageMagick
  2740. $index[$v][$filename]=$version;
  2741. }
  2742. }
  2743. }
  2744. }
  2745. if (count($index[$v])>=3 || $index[$v]['gm']) {
  2746. $this->config_array['im'] = 1;
  2747. }
  2748. if ($index[$v]['gm'] || (!$index[$v]['composite'] && $index[$v]['combine'])) {
  2749. $this->config_array['im_combine_filename']='combine';
  2750. } elseif ($index[$v]['composite'] && !$index[$v]['combine']) {
  2751. $this->config_array['im_combine_filename']='composite';
  2752. }
  2753. if (isset($index[$v]['convert']) && $this->checkIMlzw) {
  2754. $index[$v]['gif_capability'] = ''.$this->_checkImageMagickGifCapability($v);
  2755. }
  2756. }
  2757. $this->config_array['im_versions']=$index;
  2758. if (!$this->config_array['im']) {
  2759. $this->message($ext, 'No ImageMagick installation available', '
  2760. <p>
  2761. It seems that there is no adequate ImageMagick installation
  2762. available at the checked locations (' . implode(', ', $paths) . ')
  2763. <br />
  2764. An \'adequate\' installation for requires \'convert\',
  2765. \'combine\'/\'composite\' and \'identify\' to be available
  2766. </p>
  2767. ', 2);
  2768. } else {
  2769. // Get the subpart for the ImageMagick versions
  2770. $theCode = t3lib_parsehtml::getSubpart($templateFile, '###VERSIONS###');
  2771. // Get the subpart for each ImageMagick version
  2772. $rowsSubPart = t3lib_parsehtml::getSubpart($theCode, '###ROWS###');
  2773. $rows = array();
  2774. foreach ($this->config_array['im_versions'] as $p => $v) {
  2775. $ka = array();
  2776. reset($v);
  2777. while(list($ka[])=each($v)) {}
  2778. // Define the markers content
  2779. $rowsMarkers = array(
  2780. 'file' => $p,
  2781. 'type' => implode('<br />', $ka),
  2782. 'version' => implode('<br />', $v)
  2783. );
  2784. // Fill the markers in the subpart
  2785. $rows[] = t3lib_parsehtml::substituteMarkerArray(
  2786. $rowsSubPart,
  2787. $rowsMarkers,
  2788. '###|###',
  2789. TRUE,
  2790. FALSE
  2791. );
  2792. }
  2793. // Substitute the subpart for the ImageMagick versions
  2794. $theCode = t3lib_parsehtml::substituteSubpart(
  2795. $theCode,
  2796. '###ROWS###',
  2797. implode(LF, $rows)
  2798. );
  2799. // Add the content to the message array
  2800. $this->message($ext, 'Available ImageMagick/GraphicsMagick installations:', $theCode, -1);
  2801. }
  2802. // Get the template file
  2803. $formSubPart = t3lib_parsehtml::getSubpart($templateFile, '###FORM###');
  2804. // Define the markers content
  2805. $formMarkers = array(
  2806. 'actionUrl' => $this->action,
  2807. 'lzwChecked' => ($this->INSTALL['checkIM']['lzw'] ? 'checked="checked"' : ''),
  2808. 'lzwLabel' => 'Check LZW capabilities.',
  2809. 'checkPath' => 'Check this path for ImageMagick installation:',
  2810. 'imageMagickPath' => htmlspecialchars($this->INSTALL['checkIM']['path']),
  2811. 'comment' => '(Eg. "D:\wwwroot\im537\ImageMagick\" for Windows or "/usr/bin/" for Unix)',
  2812. 'send' => 'Send'
  2813. );
  2814. // Fill the markers
  2815. $formSubPart = t3lib_parsehtml::substituteMarkerArray(
  2816. $formSubPart,
  2817. $formMarkers,
  2818. '###|###',
  2819. TRUE,
  2820. FALSE
  2821. );
  2822. // Add the content to the message array
  2823. $this->message($ext, 'Search for ImageMagick:', $formSubPart, 0);
  2824. }
  2825. /**
  2826. * Checking GIF-compression capabilities of ImageMagick install
  2827. *
  2828. * @param string $path Path of ImageMagick installation
  2829. * @return string Type of compression
  2830. */
  2831. function _checkImageMagickGifCapability($path) {
  2832. if ($this->config_array['dir_typo3temp']) {
  2833. $tempPath = $this->typo3temp_path;
  2834. $uniqueName = md5(uniqid(microtime()));
  2835. $dest = $tempPath.$uniqueName.'.gif';
  2836. $src = $this->backPath.'gfx/typo3logo.gif';
  2837. if (@is_file($src) && !strstr($src, ' ') && !strstr($dest, ' ')) {
  2838. $cmd = t3lib_div::imageMagickCommand('convert', $src.' '.$dest, $path);
  2839. t3lib_utility_Command::exec($cmd);
  2840. } else die('No typo3/gfx/typo3logo.gif file!');
  2841. $out='';
  2842. if (@is_file($dest)) {
  2843. $new_info = @getimagesize($dest);
  2844. clearstatcache();
  2845. $new_size = filesize($dest);
  2846. $src_info = @getimagesize($src);
  2847. clearstatcache();
  2848. $src_size = @filesize($src);
  2849. if ($new_info[0]!=$src_info[0] || $new_info[1]!=$src_info[1] || !$new_size || !$src_size) {
  2850. $out='error';
  2851. } else {
  2852. // NONE-LZW ratio was 5.5 in test
  2853. if ($new_size/$src_size > 4) {
  2854. $out='NONE';
  2855. // NONE-RLE ratio was not tested
  2856. } elseif ($new_size/$src_size > 1.5) {
  2857. $out='RLE';
  2858. } else {
  2859. $out='LZW';
  2860. }
  2861. }
  2862. unlink($dest);
  2863. }
  2864. return $out;
  2865. }
  2866. }
  2867. /**
  2868. * Extracts the version number for ImageMagick
  2869. *
  2870. * @param string $file The program name to execute in order to find out the version number
  2871. * @param string $path Path for the above program
  2872. * @return string Version number of the found ImageMagick instance
  2873. */
  2874. function _checkImageMagick_getVersion($file, $path) {
  2875. // Temporarily override some settings
  2876. $im_version = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'];
  2877. $combine_filename = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'];
  2878. if ($file=='gm') {
  2879. $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] = 'gm';
  2880. // Work-around, preventing execution of "gm gm"
  2881. $file = 'identify';
  2882. // Work-around - GM doesn't like to be executed without any arguments
  2883. $parameters = '-version';
  2884. } else {
  2885. $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] = 'im5';
  2886. // Override the combine_filename setting
  2887. if ($file=='combine' || $file=='composite') {
  2888. $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'] = $file;
  2889. }
  2890. }
  2891. $cmd = t3lib_div::imageMagickCommand($file, $parameters, $path);
  2892. $retVal = FALSE;
  2893. t3lib_utility_Command::exec($cmd, $retVal);
  2894. $string = $retVal[0];
  2895. list(,$ver) = explode('Magick', $string);
  2896. list($ver) = explode(' ', trim($ver));
  2897. // Restore the values
  2898. $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] = $im_version;
  2899. $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'] = $combine_filename;
  2900. return trim($ver);
  2901. }
  2902. /**
  2903. * Checks database username/password/host/database
  2904. *
  2905. * @return void
  2906. */
  2907. function checkDatabase() {
  2908. $ext='Check database';
  2909. $this->message($ext);
  2910. if (!extension_loaded('mysql') && !t3lib_extMgm::isLoaded('dbal')) {
  2911. $this->message($ext, 'MySQL not available', '
  2912. <p>
  2913. PHP does not feature MySQL support (which is pretty unusual).
  2914. </p>
  2915. ', 2);
  2916. } else {
  2917. if (!TYPO3_db_host || !TYPO3_db_username) {
  2918. $this->message($ext, 'Username, password or host not set', '
  2919. <p>
  2920. You may need to enter data for these values:
  2921. <br />
  2922. Username: <strong>' . htmlspecialchars(TYPO3_db_username) . '</strong>
  2923. <br />
  2924. Host: <strong>' . htmlspecialchars(TYPO3_db_host) . '</strong>
  2925. <br />
  2926. <br />
  2927. Use the form below.
  2928. </p>
  2929. ', 2);
  2930. }
  2931. if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
  2932. $this->message($ext, 'Connected to SQL database successfully', '
  2933. <dl id="t3-install-databaseconnected">
  2934. <dt>
  2935. Username:
  2936. </dt>
  2937. <dd>
  2938. ' . htmlspecialchars(TYPO3_db_username) . '
  2939. </dd>
  2940. <dt>
  2941. Host:
  2942. </dt>
  2943. <dd>
  2944. ' . htmlspecialchars(TYPO3_db_host) . '
  2945. </dd>
  2946. </dl>
  2947. ', -1, 1);
  2948. $this->config_array['mysqlConnect']=1;
  2949. if (!TYPO3_db) {
  2950. $this->message($ext, 'No database selected', '
  2951. <p>
  2952. Currently you have no database selected.
  2953. <br />
  2954. Please select one or create a new database.
  2955. </p>
  2956. ', 3);
  2957. $this->config_array['no_database']=1;
  2958. } elseif (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
  2959. $this->message($ext, 'Database', '
  2960. <p>
  2961. \'' . htmlspecialchars(TYPO3_db) . '\' could not be selected as database!
  2962. <br />
  2963. Please select another one or create a new database.
  2964. </p>
  2965. ', 3, 1);
  2966. $this->config_array['no_database']=1;
  2967. } else {
  2968. $this->message($ext, 'Database', '
  2969. <p>
  2970. <strong>' . htmlspecialchars(TYPO3_db) . '</strong> is selected as
  2971. database.
  2972. </p>
  2973. ', 1, 1);
  2974. }
  2975. } else {
  2976. $sqlSafeModeUser = '';
  2977. if ($this->config_array['sql.safe_mode_user']) {
  2978. $sqlSafeModeUser = '
  2979. <strong>Notice:</strong>
  2980. <em>sql.safe_mode</em> is turned on, so apparently your
  2981. username to the database is the same as the scriptowner,
  2982. which is ' . $this->config_array['sql.safe_mode_user'];
  2983. }
  2984. $this->message($ext, 'Could not connect to SQL database!', '
  2985. <p>
  2986. Connecting to SQL database failed with these settings:
  2987. <br />
  2988. Username: <strong>' . htmlspecialchars(TYPO3_db_username) . '</strong>
  2989. <br />
  2990. Host: <strong>' . htmlspecialchars(TYPO3_db_host) . '</strong>
  2991. </p>
  2992. <p>
  2993. Make sure you\'re using the correct set of data.
  2994. <br />
  2995. ' . $sqlSafeModeUser . '
  2996. </p>
  2997. ', 3);
  2998. }
  2999. }
  3000. }
  3001. /**
  3002. * Prints form for updating localconf.php or updates localconf.php depending on $cmd
  3003. *
  3004. * @param string $cmd If "get_form" it outputs the form. Default is to write "localconf.php" based on input in ->INSTALL[localconf.php] array and flag ->setLocalconf
  3005. * @return string Form HTML
  3006. */
  3007. function setupGeneral($cmd='') {
  3008. switch($cmd) {
  3009. case 'get_form':
  3010. // Get the template file
  3011. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'SetupGeneral.html');
  3012. // Get the template part from the file
  3013. $form = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  3014. // Get the subpart for all modes
  3015. $allModesSubpart = t3lib_parsehtml::getSubpart($form, '###ALLMODES###');
  3016. // Define the markers content
  3017. $formMarkers['actionUrl'] = $this->action;
  3018. // Username
  3019. if (TYPO3_db_username) {
  3020. $username = TYPO3_db_username;
  3021. } elseif ($this->config_array['sql.safe_mode_user']) {
  3022. $username = $this->config_array['sql.safe_mode_user'];
  3023. // Get the subpart for the sql safe mode user
  3024. $sqlSafeModeUserSubpart = t3lib_parsehtml::getSubpart($allModesSubpart, '###SQLSAFEMODEUSERSUBPART###');
  3025. // Define the markers content
  3026. $sqlSafeModeUserMarkers = array(
  3027. 'labelSqlSafeModeUser' => 'sql.safe_mode_user:',
  3028. 'sqlSafeModeUser' => $this->config_array['sql.safe_mode_user']
  3029. );
  3030. // Fill the markers in the subpart
  3031. $sqlSafeModeUserSubpart = t3lib_parsehtml::substituteMarkerArray(
  3032. $sqlSafeModeUserSubpart,
  3033. $sqlSafeModeUserMarkers,
  3034. '###|###',
  3035. TRUE,
  3036. FALSE
  3037. );
  3038. }
  3039. // Get the subpart for all modes
  3040. $allModesSubpart = t3lib_parsehtml::substituteSubpart(
  3041. $allModesSubpart,
  3042. '###SQLSAFEMODEUSERSUBPART###',
  3043. $sqlSafeModeUserSubpart
  3044. );
  3045. // Define the markers content
  3046. $allModesMarkers = array(
  3047. 'labelUsername' => 'Username:',
  3048. 'username' => htmlspecialchars($username),
  3049. 'labelPassword' => 'Password:',
  3050. 'password' => htmlspecialchars(TYPO3_db_password),
  3051. 'labelHost' => 'Host:',
  3052. 'host' => htmlspecialchars(TYPO3_db_host),
  3053. 'labelDatabase' => 'Database:',
  3054. 'labelCreateDatabase' => 'Create database?'
  3055. );
  3056. // Get the subpart for the database list
  3057. $databasesSubpart = t3lib_parsehtml::getSubpart($allModesSubpart, '###DATABASELIST###');
  3058. if ($this->config_array['mysqlConnect']) {
  3059. // Get the subpart when database is available
  3060. $databaseAvailableSubpart = t3lib_parsehtml::getSubpart($databasesSubpart, '###DATABASEAVAILABLE###');
  3061. // Get the subpart for each database table
  3062. $databaseItemSubpart = t3lib_parsehtml::getSubpart($databaseAvailableSubpart, '###DATABASEITEM###');
  3063. $dbArr = $this->getDatabaseList();
  3064. $dbIncluded=0;
  3065. $databaseItems = array();
  3066. foreach ($dbArr as $dbname) {
  3067. // Define the markers content
  3068. $databaseItemMarkers = array(
  3069. 'databaseSelected' => '',
  3070. 'databaseName' => htmlspecialchars($dbname),
  3071. 'databaseValue' => htmlspecialchars($dbname)
  3072. );
  3073. if ($dbname == TYPO3_db) {
  3074. $databaseItemMarkers['databaseSelected'] = 'selected="selected"';
  3075. }
  3076. // Fill the markers in the subpart
  3077. $databaseItems[] = t3lib_parsehtml::substituteMarkerArray(
  3078. $databaseItemSubpart,
  3079. $databaseItemMarkers,
  3080. '###|###',
  3081. TRUE,
  3082. FALSE
  3083. );
  3084. if ($dbname==TYPO3_db) $dbIncluded=1;
  3085. }
  3086. if (!$dbIncluded && TYPO3_db) {
  3087. $databaseItemMarkers['databaseName'] = htmlspecialchars(TYPO3_db);
  3088. $databaseItemMarkers['databaseSelected'] = 'selected="selected"';
  3089. $databaseItemMarkers['databaseValue'] = htmlspecialchars(TYPO3_db) . ' (NO ACCESS!)';
  3090. // Fill the markers in the subpart
  3091. $databaseItems[] = t3lib_parsehtml::substituteMarkerArray(
  3092. $databaseItemSubpart,
  3093. $databaseItemMarkers,
  3094. '###|###',
  3095. TRUE,
  3096. FALSE
  3097. );
  3098. }
  3099. // Substitute the subpart for the database tables
  3100. $databaseAvailableSubpart = t3lib_parsehtml::substituteSubpart(
  3101. $databaseAvailableSubpart,
  3102. '###DATABASEITEM###',
  3103. implode(LF, $databaseItems)
  3104. );
  3105. } else {
  3106. // Get the subpart when the database is not available
  3107. $databaseNotAvailableSubpart = t3lib_parsehtml::getSubpart($databasesSubpart, '###DATABASENOTAVAILABLE###');
  3108. $databaseNotAvailableMarkers = array(
  3109. 'typo3Db' => htmlspecialchars(TYPO3_db),
  3110. 'labelNoDatabase' => '
  3111. (Database cannot be selected. Make sure that username, password and host
  3112. are set correctly. If MySQL does not allow persistent connections,
  3113. check that $TYPO3_CONF_VARS[\'SYS\'][\'no_pconnect\'] is set to "1".)
  3114. '
  3115. );
  3116. // Fill the markers in the subpart
  3117. $databaseNotAvailableSubpart = t3lib_parsehtml::substituteMarkerArray(
  3118. $databaseNotAvailableSubpart,
  3119. $databaseNotAvailableMarkers,
  3120. '###|###',
  3121. TRUE,
  3122. FALSE
  3123. );
  3124. }
  3125. // Substitute the subpart when database is available
  3126. $databasesSubpart = t3lib_parsehtml::substituteSubpart(
  3127. $databasesSubpart,
  3128. '###DATABASEAVAILABLE###',
  3129. $databaseAvailableSubpart
  3130. );
  3131. // Substitute the subpart when database is not available
  3132. $databasesSubpart = t3lib_parsehtml::substituteSubpart(
  3133. $databasesSubpart,
  3134. '###DATABASENOTAVAILABLE###',
  3135. $databaseNotAvailableSubpart
  3136. );
  3137. // Substitute the subpart for the databases
  3138. $allModesSubpart = t3lib_parsehtml::substituteSubpart(
  3139. $allModesSubpart,
  3140. '###DATABASELIST###',
  3141. $databasesSubpart
  3142. );
  3143. // Fill the markers in the subpart for all modes
  3144. $allModesSubpart = t3lib_parsehtml::substituteMarkerArray(
  3145. $allModesSubpart,
  3146. $allModesMarkers,
  3147. '###|###',
  3148. TRUE,
  3149. FALSE
  3150. );
  3151. // Substitute the subpart for all modes
  3152. $form = t3lib_parsehtml::substituteSubpart(
  3153. $form,
  3154. '###ALLMODES###',
  3155. $allModesSubpart
  3156. );
  3157. if ($this->mode!='123') {
  3158. // Get the subpart for the regular mode
  3159. $regularModeSubpart = t3lib_parsehtml::getSubpart($form, '###REGULARMODE###');
  3160. // Define the markers content
  3161. $regularModeMarkers = array(
  3162. 'labelSiteName' => 'Site name:',
  3163. 'siteName' => htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']),
  3164. 'labelEncryptionKey' => 'Encryption key:',
  3165. 'encryptionKey' => htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']),
  3166. 'labelGenerateRandomKey' => 'Generate random key'
  3167. );
  3168. // Other
  3169. $fA = $this->setupGeneralCalculate();
  3170. $regularModeMarkers['labelCurrentValueIs'] = 'current value is';
  3171. // Disable exec function
  3172. if (is_array($fA['disable_exec_function'])) {
  3173. // Get the subpart for the disable exec function
  3174. $disableExecFunctionSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###DISABLEEXECFUNCTIONSUBPART###');
  3175. $regularModeMarkers['labelDisableExecFunction'] = '[BE][disable_exec_function]=';
  3176. $regularModeMarkers['strongDisableExecFunction'] = (integer) current($fA['disable_exec_function']);
  3177. $regularModeMarkers['defaultDisableExecFunction'] = (integer) $GLOBALS['TYPO3_CONF_VARS']['BE']['disable_exec_function'];
  3178. $regularModeMarkers['disableExecFunction'] = (integer) current($fA['disable_exec_function']);
  3179. // Fill the markers in the subpart
  3180. $disableExecFunctionSubpart = t3lib_parsehtml::substituteMarkerArray(
  3181. $disableExecFunctionSubpart,
  3182. $regularModeMarkers,
  3183. '###|###',
  3184. TRUE,
  3185. FALSE
  3186. );
  3187. }
  3188. // Substitute the subpart for the disable exec function
  3189. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3190. $regularModeSubpart,
  3191. '###DISABLEEXECFUNCTIONSUBPART###',
  3192. $disableExecFunctionSubpart
  3193. );
  3194. // GDlib
  3195. if (is_array($fA['gdlib'])) {
  3196. // Get the subpart for the disable gd lib
  3197. $gdLibSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###DISABLEGDLIB###');
  3198. $regularModeMarkers['labelGdLib'] = '[GFX][gdlib]=';
  3199. $regularModeMarkers['strongGdLib'] = (integer) current($fA['gdlib']);
  3200. $regularModeMarkers['defaultGdLib'] = (integer) $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
  3201. $regularModeMarkers['gdLib'] = (integer) current($fA['gdlib']);
  3202. // Fill the markers in the subpart
  3203. $gdLibSubpart = t3lib_parsehtml::substituteMarkerArray(
  3204. $gdLibSubpart,
  3205. $regularModeMarkers,
  3206. '###|###',
  3207. TRUE,
  3208. FALSE
  3209. );
  3210. }
  3211. // Substitute the subpart for the disable gdlib
  3212. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3213. $regularModeSubpart,
  3214. '###DISABLEGDLIB###',
  3215. $gdLibSubpart
  3216. );
  3217. // GDlib PNG
  3218. if (is_array($fA['gdlib_png']) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
  3219. // Get the subpart for the gdlib png
  3220. $gdLibPngSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###GDLIBPNGSUBPART###');
  3221. // Get the subpart for the dropdown options
  3222. $gdLibPngOptionSubpart = t3lib_parsehtml::getSubpart($gdLibPngSubpart, '###GDLIBPNGOPTION###');
  3223. $gdLibPngLabels = $this->setLabelValueArray($fA['gdlib_png'], 2);
  3224. reset($gdLibPngLabels);
  3225. $regularModeMarkers['labelGdLibPng'] = '[GFX][gdlib_png]=';
  3226. $regularModeMarkers['strongGdLibPng'] = (string) current($gdLibPngLabels);
  3227. $regularModeMarkers['defaultGdLibPng'] = (integer) $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'];
  3228. $gdLibPngOptions = array();
  3229. foreach ($gdLibPngLabels as $k => $v) {
  3230. list($cleanV) = explode('|', $fA['gdlib_png'][$k]);
  3231. $gdLibPngMarker['value'] = htmlspecialchars($fA['gdlib_png'][$k]);
  3232. $gdLibPngMarker['data'] = htmlspecialchars($v);
  3233. if (!strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'], $cleanV)) {
  3234. $gdLibPngMarker['selected'] = 'selected="selected"';
  3235. }
  3236. // Fill the markers in the subpart
  3237. $gdLibPngOptions[] = t3lib_parsehtml::substituteMarkerArray(
  3238. $gdLibPngOptionSubpart,
  3239. $gdLibPngMarker,
  3240. '###|###',
  3241. TRUE,
  3242. FALSE
  3243. );
  3244. }
  3245. // Substitute the subpart for the dropdown options
  3246. $gdLibPngSubpart = t3lib_parsehtml::substituteSubpart(
  3247. $gdLibPngSubpart,
  3248. '###GDLIBPNGOPTION###',
  3249. implode(LF, $gdLibPngOptions)
  3250. );
  3251. // Fill the markers in the subpart
  3252. $gdLibPngSubpart = t3lib_parsehtml::substituteMarkerArray(
  3253. $gdLibPngSubpart,
  3254. $regularModeMarkers,
  3255. '###|###',
  3256. TRUE,
  3257. FALSE
  3258. );
  3259. }
  3260. // Substitute the subpart for the gdlib png
  3261. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3262. $regularModeSubpart,
  3263. '###GDLIBPNGSUBPART###',
  3264. $gdLibPngSubpart
  3265. );
  3266. // ImageMagick
  3267. if (is_array($fA['im'])) {
  3268. // Get the subpart for ImageMagick
  3269. $imageMagickSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###IMAGEMAGICKSUBPART###');
  3270. // Define the markers content
  3271. $regularModeMarkers['labelImageMagick'] = '[GFX][im]=';
  3272. $regularModeMarkers['strongImageMagick'] = (string) current($fA['im']);
  3273. $regularModeMarkers['defaultImageMagick'] = (integer) $GLOBALS['TYPO3_CONF_VARS']['GFX']['im'];
  3274. $regularModeMarkers['imageMagick'] = (integer) current($fA['im']);
  3275. // Fill the markers in the subpart
  3276. $imageMagickSubpart = t3lib_parsehtml::substituteMarkerArray(
  3277. $imageMagickSubpart,
  3278. $regularModeMarkers,
  3279. '###|###',
  3280. TRUE,
  3281. FALSE
  3282. );
  3283. // IM Combine Filename
  3284. // Get the subpart for ImageMagick Combine filename
  3285. $imCombineFileNameSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###IMCOMBINEFILENAMESUBPART###');
  3286. // Define the markers content
  3287. $regularModeMarkers['labelImCombineFilename'] = '[GFX][im_combine_filename]';
  3288. $regularModeMarkers['strongImCombineFilename'] = (string) current($fA['im_combine_filename']);
  3289. $regularModeMarkers['defaultImCombineFilename'] = (string) $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'];
  3290. $regularModeMarkers['imCombineFilename'] = (string) ($fA['im_combine_filename'] ? current($fA['im_combine_filename']) : 'combine');
  3291. // Fill the markers in the subpart
  3292. $imCombineFileNameSubpart = t3lib_parsehtml::substituteMarkerArray(
  3293. $imCombineFileNameSubpart,
  3294. $regularModeMarkers,
  3295. '###|###',
  3296. TRUE,
  3297. FALSE
  3298. );
  3299. // IM Version 5
  3300. // Get the subpart for ImageMagick Version 5
  3301. $imVersion5Subpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###IMVERSION5SUBPART###');
  3302. // Define the markers content
  3303. $regularModeMarkers['labelImVersion5'] = '[GFX][im_version_5]=';
  3304. $regularModeMarkers['strongImVersion5'] = (string) current($fA['im_version_5']);
  3305. $regularModeMarkers['defaultImVersion5'] = (string) $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'];
  3306. $regularModeMarkers['imVersion5'] = (string) ($fA['im_version_5'] ? current($fA['im_version_5']) : '');
  3307. // Fill the markers in the subpart
  3308. $imVersion5Subpart = t3lib_parsehtml::substituteMarkerArray(
  3309. $imVersion5Subpart,
  3310. $regularModeMarkers,
  3311. '###|###',
  3312. TRUE,
  3313. FALSE
  3314. );
  3315. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
  3316. // IM Path
  3317. if (is_array($fA['im_path'])) {
  3318. // Get the subpart for ImageMagick path
  3319. $imPathSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###IMPATHSUBPART###');
  3320. $labelImPath = $this->setLabelValueArray($fA['im_path'], 1);
  3321. reset($labelImPath);
  3322. $imPath = $this->setLabelValueArray($fA['im_path'], 0);
  3323. reset($imPath);
  3324. // Define the markers content
  3325. $regularModeMarkers['labelImPath'] = '[GFX][im_path]=';
  3326. $regularModeMarkers['strongImPath'] = (string) current($labelImPath);
  3327. $regularModeMarkers['defaultImPath'] = (string) $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path'];
  3328. $regularModeMarkers['ImPath'] = (string) current($imPath);
  3329. // Fill the markers in the subpart
  3330. $imPathSubpart = t3lib_parsehtml::substituteMarkerArray(
  3331. $imPathSubpart,
  3332. $regularModeMarkers,
  3333. '###|###',
  3334. TRUE,
  3335. FALSE
  3336. );
  3337. }
  3338. // IM Path LZW
  3339. if (is_array($fA['im_path_lzw'])) {
  3340. // Get the subpart for ImageMagick lzw path
  3341. $imPathLzwSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###IMPATHLZWSUBPART###');
  3342. // Get the subpart for ImageMagick lzw path dropdown options
  3343. $imPathOptionSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###IMPATHLZWOPTION###');
  3344. $labelImPathLzw = $this->setLabelValueArray($fA['im_path_lzw'], 1);
  3345. reset($labelImPathLzw);
  3346. $imPathLzw = $this->setLabelValueArray($fA['im_path_lzw'], 0);
  3347. reset($imPathLzw);
  3348. // Define the markers content
  3349. $regularModeMarkers['labelImPathLzw'] = '[GFX][im_path_lzw]=';
  3350. $regularModeMarkers['strongImPathLzw'] = (string) current($labelImPathLzw);
  3351. $regularModeMarkers['defaultImPathLzw'] = (string) $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'];
  3352. $regularModeMarkers['ImPathLzw'] = (string) current($imPathLzw);
  3353. $imPathLzwOptions = array();
  3354. foreach ($labelImPathLzw as $k => $v) {
  3355. list($cleanV) = explode('|', $fA['im_path_lzw'][$k]);
  3356. // Define the markers content
  3357. $imPathLzwMarker = array(
  3358. 'value' => htmlspecialchars($fA['im_path_lzw'][$k]),
  3359. 'data' => htmlspecialchars($v)
  3360. );
  3361. if (!strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'], $cleanV)) {
  3362. $imPathLzwMarker['selected'] = 'selected="selected"';
  3363. }
  3364. // Fill the markers in the subpart
  3365. $imPathLzwOptions[] = t3lib_parsehtml::substituteMarkerArray(
  3366. $imPathOptionSubpart,
  3367. $imPathLzwMarker,
  3368. '###|###',
  3369. TRUE,
  3370. FALSE
  3371. );
  3372. }
  3373. // Substitute the subpart for ImageMagick lzw path dropdown options
  3374. $imPathLzwSubpart = t3lib_parsehtml::substituteSubpart(
  3375. $imPathLzwSubpart,
  3376. '###IMPATHLZWOPTION###',
  3377. implode(LF, $imPathLzwOptions)
  3378. );
  3379. // Fill the markers in the subpart
  3380. $imPathLzwSubpart = t3lib_parsehtml::substituteMarkerArray(
  3381. $imPathLzwSubpart,
  3382. $regularModeMarkers,
  3383. '###|###',
  3384. TRUE,
  3385. FALSE
  3386. );
  3387. }
  3388. }
  3389. }
  3390. // Substitute the subpart for ImageMagick
  3391. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3392. $regularModeSubpart,
  3393. '###IMAGEMAGICKSUBPART###',
  3394. $imageMagickSubpart
  3395. );
  3396. // Substitute the subpart for ImageMagick Combine filename
  3397. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3398. $regularModeSubpart,
  3399. '###IMCOMBINEFILENAMESUBPART###',
  3400. $imCombineFileNameSubpart
  3401. );
  3402. // Substitute the subpart for ImageMagick Version 5
  3403. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3404. $regularModeSubpart,
  3405. '###IMVERSION5SUBPART###',
  3406. $imVersion5Subpart
  3407. );
  3408. // Substitute the subpart for ImageMagick path
  3409. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3410. $regularModeSubpart,
  3411. '###IMPATHSUBPART###',
  3412. $imPathSubpart
  3413. );
  3414. // Substitute the subpart for ImageMagick lzw path
  3415. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3416. $regularModeSubpart,
  3417. '###IMPATHLZWSUBPART###',
  3418. $imPathLzwSubpart
  3419. );
  3420. // TrueType Font dpi
  3421. // Get the subpart for TrueType dpi
  3422. $ttfDpiSubpart = t3lib_parsehtml::getSubpart($regularModeSubpart, '###TTFDPISUBPART###');
  3423. // Define the markers content
  3424. $regularModeMarkers['labelTtfDpi'] = '[GFX][TTFdpi]=';
  3425. $regularModeMarkers['ttfDpi'] = htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['TTFdpi']);
  3426. // Fill the markers in the subpart
  3427. $ttfDpiSubpart = t3lib_parsehtml::substituteMarkerArray(
  3428. $ttfDpiSubpart,
  3429. $regularModeMarkers,
  3430. '###|###',
  3431. TRUE,
  3432. FALSE
  3433. );
  3434. // Substitute the subpart for TrueType dpi
  3435. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  3436. $regularModeSubpart,
  3437. '###TTFDPISUBPART###',
  3438. $ttfDpiSubpart
  3439. );
  3440. // Fill the markers in the regular mode subpart
  3441. $regularModeSubpart = t3lib_parsehtml::substituteMarkerArray(
  3442. $regularModeSubpart,
  3443. $regularModeMarkers,
  3444. '###|###',
  3445. TRUE,
  3446. FALSE
  3447. );
  3448. }
  3449. $formMarkers['labelUpdateLocalConf'] = 'Update localconf.php';
  3450. $formMarkers['labelNotice'] = 'NOTICE:';
  3451. $formMarkers['labelCommentUpdateLocalConf'] = 'By clicking this button, localconf.php is updated with new values for the parameters listed above!';
  3452. // Substitute the subpart for regular mode
  3453. $form = t3lib_parsehtml::substituteSubpart(
  3454. $form,
  3455. '###REGULARMODE###',
  3456. $regularModeSubpart
  3457. );
  3458. // Fill the markers
  3459. $out = t3lib_parsehtml::substituteMarkerArray(
  3460. $form,
  3461. $formMarkers,
  3462. '###|###',
  3463. TRUE,
  3464. FALSE
  3465. );
  3466. break;
  3467. default:
  3468. if (is_array($this->INSTALL['localconf.php'])) {
  3469. $lines = $this->writeToLocalconf_control();
  3470. // New database?
  3471. if (trim($this->INSTALL['localconf.php']['NEW_DATABASE_NAME'])) {
  3472. $newdbname=trim($this->INSTALL['localconf.php']['NEW_DATABASE_NAME']);
  3473. if (!preg_match('/[^[:alnum:]_-]/', $newdbname)) {
  3474. if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
  3475. if ($GLOBALS['TYPO3_DB']->admin_query('CREATE DATABASE ' . $newdbname . ' CHARACTER SET utf8')) {
  3476. $this->INSTALL['localconf.php']['typo_db'] = $newdbname;
  3477. $this->messages[]= "Database '".$newdbname."' created";
  3478. } else {
  3479. $this->errorMessages[] = '
  3480. Could not create database \'' .
  3481. $newdbname . '\' (...not created)
  3482. ';
  3483. }
  3484. } else {
  3485. $this->errorMessages[] = '
  3486. Could not connect to database when creating
  3487. database \'' . $newdbname . '\' (...not
  3488. created)
  3489. ';
  3490. }
  3491. } else {
  3492. $this->errorMessages[] = '
  3493. The NEW database name \'' . $newdbname . '\' was
  3494. not alphanumeric, a-zA-Z0-9_- (...not created)
  3495. ';
  3496. }
  3497. }
  3498. // Parsing values
  3499. foreach ($this->INSTALL['localconf.php'] as $key => $value) {
  3500. switch((string)$key) {
  3501. case 'typo_db_username':
  3502. if (strlen($value)<50) {
  3503. if (strcmp(TYPO3_db_username, $value))
  3504. $this->setValueInLocalconfFile($lines, '$typo_db_username', trim($value));
  3505. } else {
  3506. $this->errorMessages[] = '
  3507. Username \'' . $value . '\' was longer
  3508. than 50 chars (...not saved)
  3509. ';
  3510. }
  3511. break;
  3512. case 'typo_db_password':
  3513. if (strlen($value)<50) {
  3514. if (strcmp(TYPO3_db_password, $value))
  3515. $this->setValueInLocalconfFile($lines, '$typo_db_password', trim($value));
  3516. } else {
  3517. $this->errorMessages[] = '
  3518. Password was longer than 50 chars (...not saved)
  3519. ';
  3520. }
  3521. break;
  3522. case 'typo_db_host':
  3523. if (preg_match('/^[a-zA-Z0-9_\.-]+(:.+)?$/', $value) && strlen($value)<50) {
  3524. if (strcmp(TYPO3_db_host, $value))
  3525. $this->setValueInLocalconfFile($lines, '$typo_db_host', $value);
  3526. } else {
  3527. $this->errorMessages[] = '
  3528. Host \'' . $value . '\' was not
  3529. alphanumeric (a-z, A-Z, 0-9 or _-.), or
  3530. longer than 50 chars (...not saved)
  3531. ';
  3532. }
  3533. break;
  3534. case 'typo_db':
  3535. if (strlen($value)<50) {
  3536. if (strcmp(TYPO3_db, $value))
  3537. $this->setValueInLocalconfFile($lines, '$typo_db', trim($value));
  3538. } else {
  3539. $this->errorMessages[] = '
  3540. Database name \'' . $value . '\' was
  3541. longer than 50 chars (...not saved)
  3542. ';
  3543. }
  3544. break;
  3545. case 'disable_exec_function':
  3546. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['BE']['disable_exec_function'], $value))
  3547. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'BE\'][\'disable_exec_function\']', $value ? 1 : 0);
  3548. break;
  3549. case 'sitename':
  3550. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], $value))
  3551. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'SYS\'][\'sitename\']', $value);
  3552. break;
  3553. case 'encryptionKey':
  3554. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], $value))
  3555. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'SYS\'][\'encryptionKey\']', $value);
  3556. break;
  3557. case 'compat_version':
  3558. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['SYS']['compat_version'], $value))
  3559. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'SYS\'][\'compat_version\']', $value);
  3560. break;
  3561. case 'im_combine_filename':
  3562. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'], $value))
  3563. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'GFX\'][\'im_combine_filename\']', $value);
  3564. break;
  3565. case 'gdlib':
  3566. case 'gdlib_png':
  3567. case 'im':
  3568. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX'][$key], $value)) {
  3569. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'GFX\'][\'' . $key . '\']', ($value ? 1 : 0));
  3570. }
  3571. break;
  3572. case 'im_path':
  3573. list($value, $version) = explode('|', $value);
  3574. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX'][$key], $value)) {
  3575. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'GFX\'][\'' . $key . '\']', $value);
  3576. }
  3577. if (doubleval($version) > 0 && doubleval($version) < 4) {
  3578. // Assume GraphicsMagick
  3579. $value_ext = 'gm';
  3580. } else {
  3581. // Assume ImageMagick 6.x
  3582. $value_ext = 'im6';
  3583. }
  3584. if (strcmp(strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5']), $value_ext)) {
  3585. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'GFX\'][\'im_version_5\']', $value_ext);
  3586. }
  3587. break;
  3588. case 'im_path_lzw':
  3589. list($value) = explode('|', $value);
  3590. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX'][$key], $value)) {
  3591. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'GFX\'][\'' . $key . '\']', $value);
  3592. }
  3593. break;
  3594. case 'TTFdpi':
  3595. if (strcmp($GLOBALS['TYPO3_CONF_VARS']['GFX']['TTFdpi'], $value))
  3596. $this->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'GFX\'][\'TTFdpi\']', $value);
  3597. break;
  3598. }
  3599. }
  3600. // Hook to modify localconf.php lines in the 1-2-3 installer
  3601. if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['writeLocalconf'])) {
  3602. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['writeLocalconf'] as $classData) {
  3603. $hookObject = t3lib_div::getUserObj($classData);
  3604. $hookObject->executeWriteLocalconf($lines, $this->step, $this);
  3605. }
  3606. }
  3607. $this->writeToLocalconf_control($lines);
  3608. }
  3609. break;
  3610. }
  3611. return $out;
  3612. }
  3613. /**
  3614. * Writes or returns lines from localconf.php
  3615. *
  3616. * @param array $lines Array of lines to write back to localconf.php. Possibly
  3617. * @param boolean $showOutput If TRUE then print what has been done.
  3618. * @return mixed If $lines is not an array it will return an array with the lines from localconf.php. Otherwise it will return a status string, either "continue" (updated) or "nochange" (not updated)
  3619. * @see parent::writeToLocalconf_control()
  3620. */
  3621. function writeToLocalconf_control($lines='', $showOutput=TRUE) {
  3622. // Get the template file
  3623. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'WriteToLocalConfControl.html');
  3624. $returnVal = parent::writeToLocalconf_control($lines);
  3625. if ($showOutput) {
  3626. switch($returnVal) {
  3627. case 'continue':
  3628. // Get the template part from the file
  3629. $template = t3lib_parsehtml::getSubpart($templateFile, '###CONTINUE###');
  3630. // Get the subpart for messages
  3631. $messagesSubPart = t3lib_parsehtml::getSubpart($template, '###MESSAGES###');
  3632. $messages = array();
  3633. foreach ($this->messages as $message) {
  3634. // Define the markers content
  3635. $messagesMarkers['message'] = $message;
  3636. // Fill the markers in the subpart
  3637. $messages[] = t3lib_parsehtml::substituteMarkerArray(
  3638. $messagesSubPart,
  3639. $messagesMarkers,
  3640. '###|###',
  3641. TRUE,
  3642. FALSE
  3643. );
  3644. }
  3645. // Substitute the subpart for messages
  3646. $content = t3lib_parsehtml::substituteSubpart(
  3647. $template,
  3648. '###MESSAGES###',
  3649. implode(LF, $messages)
  3650. );
  3651. // Define the markers content
  3652. $markers = array(
  3653. 'header' => 'Writing to \'localconf.php\'',
  3654. 'action' => $this->action,
  3655. 'label' => 'Click to continue...'
  3656. );
  3657. // Fill the markers
  3658. $content = t3lib_parsehtml::substituteMarkerArray(
  3659. $content,
  3660. $markers,
  3661. '###|###',
  3662. TRUE,
  3663. FALSE
  3664. );
  3665. $this->outputExitBasedOnStep($content);
  3666. break;
  3667. case 'nochange':
  3668. // Get the template part from the file
  3669. $template = t3lib_parsehtml::getSubpart($templateFile, '###NOCHANGE###');
  3670. // Define the markers content
  3671. $markers = array(
  3672. 'header' => 'Writing to \'localconf.php\'',
  3673. 'message' => 'No values were changed, so nothing is updated!',
  3674. 'action' => $this->action,
  3675. 'label' => 'Click to continue...'
  3676. );
  3677. // Fill the markers
  3678. $content = t3lib_parsehtml::substituteMarkerArray(
  3679. $template,
  3680. $markers,
  3681. '###|###',
  3682. TRUE,
  3683. FALSE
  3684. );
  3685. $this->outputExitBasedOnStep($content);
  3686. break;
  3687. }
  3688. }
  3689. return $returnVal;
  3690. }
  3691. /**
  3692. * If in 1-2-3 mode, send a redirect header response with the action and exit
  3693. * otherwise send output to output() function
  3694. *
  3695. * @param string $content The HTML to output
  3696. * @return void
  3697. */
  3698. function outputExitBasedOnStep($content) {
  3699. if ($this->step) {
  3700. t3lib_utility_Http::redirect($this->action);
  3701. } else {
  3702. $this->output($this->outputWrapper($content));
  3703. }
  3704. exit;
  3705. }
  3706. /**
  3707. * This appends something to value in the input array based on $type. Private.
  3708. *
  3709. * @param array $arr
  3710. * @param integer $type
  3711. * @return array
  3712. */
  3713. function setLabelValueArray($arr, $type) {
  3714. foreach ($arr as $k => $v) {
  3715. if($this->config_array['im_versions'][$v]['gm']) {
  3716. $program = 'gm';
  3717. } else {
  3718. $program = 'convert';
  3719. }
  3720. switch($type) {
  3721. // value, im
  3722. case 0:
  3723. $arr[$k].='|'.$this->config_array['im_versions'][$v][$program];
  3724. break;
  3725. // labels, im
  3726. case 1:
  3727. if($this->config_array['im_versions'][$v][$program]) {
  3728. $arr[$k].= ' ('.$this->config_array['im_versions'][$v][$program];
  3729. $arr[$k].= ($this->config_array['im_versions'][$v]['gif_capability'] ? ', '.$this->config_array['im_versions'][$v]['gif_capability'] : '');
  3730. $arr[$k].= ')';
  3731. } else {
  3732. $arr[$k].= '';
  3733. }
  3734. break;
  3735. // labels, gd
  3736. case 2:
  3737. $arr[$k].=' ('.($v==1?'PNG':'GIF').')';
  3738. break;
  3739. }
  3740. }
  3741. return $arr;
  3742. }
  3743. /**
  3744. * Returns the list of available databases (with access-check based on username/password)
  3745. *
  3746. * @return array List of available databases
  3747. */
  3748. public function getDatabaseList() {
  3749. $dbArr = array();
  3750. if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
  3751. $dbArr = $GLOBALS['TYPO3_DB']->admin_get_dbs();
  3752. }
  3753. // remove some database names that MySQL uses internally from the list of choosable DB names
  3754. $reservedDatabaseNames = array('mysql', 'information_schema');
  3755. $databaseList = array_diff($dbArr, $reservedDatabaseNames);
  3756. return $databaseList;
  3757. }
  3758. /**
  3759. * Calculates the suggested setup that should be written to localconf.php
  3760. *
  3761. * If safe_mode
  3762. * - disable_exec_function = 1
  3763. * - im = 0
  3764. *
  3765. * if PNG/GIF/GD
  3766. * - disable gdlib if nothing
  3767. * - select png/gif if only one of them is available, else PNG/GIF selector, defaulting to GIF
  3768. * - (safe_mode is on)
  3769. * - im_path (default to 4.2.9, preferable with LZW) im_ver5-flag is set based on im_path being 4.2.9 or 5+
  3770. * - im_path_lzw (default to LZW version, pref. 4.2.9)
  3771. *
  3772. * @return array Suggested setup
  3773. */
  3774. function setupGeneralCalculate() {
  3775. $formArray['disable_exec_function']=array(0);
  3776. $formArray['im_path']=array('');
  3777. $formArray['im_path_lzw']=array('');
  3778. $formArray['im_combine_filename']=array('');
  3779. $formArray['im_version_5']=array('');
  3780. $formArray['im']=array(1);
  3781. $formArray['gdlib']=array(1);
  3782. if ($this->config_array['gd'] && ($this->config_array['gd_gif'] || $this->config_array['gd_png'])) {
  3783. if ($this->config_array['gd_gif'] && !$this->config_array['gd_png']) {
  3784. $formArray['gdlib_png']=array(0);
  3785. } elseif (!$this->config_array['gd_gif'] && $this->config_array['gd_png']) {
  3786. $formArray['gdlib_png']=array(1);
  3787. } else {
  3788. $formArray['gdlib_png']=array(0, 1);
  3789. }
  3790. } else {
  3791. $formArray['gdlib']=array(0);
  3792. }
  3793. if ($this->config_array['safemode']) {
  3794. $formArray['disable_exec_function']=array(1);
  3795. }
  3796. if ($this->config_array['im']) {
  3797. $formArray['im'] = array(1);
  3798. $found = $LZW_found = 0;
  3799. $totalArr = array();
  3800. foreach ($this->config_array['im_versions'] as $path => $dat) {
  3801. if (count($dat)>=3) {
  3802. if (doubleval($dat['convert'])<5) {
  3803. $formArray['im_version_5']=array(0);
  3804. if ($dat['gif_capability']=='LZW') {
  3805. $formArray['im_path']=array($path);
  3806. $found=2;
  3807. } elseif ($found<2) {
  3808. $formArray['im_path']=array($path);
  3809. $found=1;
  3810. }
  3811. } elseif (doubleval($dat['convert']) >= 6) {
  3812. $formArray['im_version_5'] = array('im6');
  3813. if ($dat['gif_capability'] == 'LZW') {
  3814. $formArray['im_path'] = array($path);
  3815. $found = 2;
  3816. } elseif ($found < 2) {
  3817. $formArray['im_path'] = array($path);
  3818. $found = 1;
  3819. }
  3820. }
  3821. } elseif ($dat['gm']) {
  3822. $formArray['im_version_5']=array('gm');
  3823. if ($dat['gif_capability']=='LZW') {
  3824. $formArray['im_path']=array($path);
  3825. $found=2;
  3826. } elseif ($found<2) {
  3827. $formArray['im_path']=array($path);
  3828. $found=1;
  3829. }
  3830. }
  3831. if ($dat['gif_capability']=='LZW') {
  3832. if (doubleval($dat['convert'])<5 || !$LZW_found) {
  3833. $formArray['im_path_lzw']=array($path);
  3834. $LZW_found=1;
  3835. }
  3836. } elseif ($dat['gif_capability']=='RLE' && !$LZW_found) {
  3837. $formArray['im_path_lzw']=array($path);
  3838. }
  3839. $totalArr[]=$path;
  3840. }
  3841. $formArray['im_path']=array_unique(array_merge($formArray['im_path'], $totalArr));
  3842. $formArray['im_path_lzw']=array_unique(array_merge($formArray['im_path_lzw'], $totalArr));
  3843. $formArray['im_combine_filename']=array($this->config_array['im_combine_filename']);
  3844. } else {
  3845. $formArray['im']=array(0);
  3846. }
  3847. return $formArray;
  3848. }
  3849. /**
  3850. * Returns TRUE if TTF lib is installed.
  3851. *
  3852. * @return boolean TRUE if TrueType support
  3853. */
  3854. function isTTF() {
  3855. // Return right away if imageTTFtext does not exist.
  3856. if (!function_exists('imagettftext')) {
  3857. return 0;
  3858. }
  3859. // try, print truetype font:
  3860. $im = @imagecreate(300, 50);
  3861. $background_color = imagecolorallocate($im, 255, 255, 55);
  3862. $text_color = imagecolorallocate($im, 233, 14, 91);
  3863. $test = @imagettftext($im, t3lib_div::freetypeDpiComp(20), 0, 10, 20, $text_color, PATH_t3lib . '/fonts/vera.ttf', 'Testing Truetype support');
  3864. if (t3lib_div::_GP('testingTrueTypeSupport')) {
  3865. if ($this->isGIF()) {
  3866. header('Content-type: image/gif');
  3867. imagegif($im);
  3868. } else {
  3869. header('Content-type: image/png');
  3870. imagepng($im);
  3871. }
  3872. exit;
  3873. }
  3874. return (is_array($test) ? 1 : 0);
  3875. }
  3876. /**
  3877. * Checks if the essential PHP modules are loaded
  3878. *
  3879. * @return array list of modules which are missing
  3880. */
  3881. protected function getMissingPhpModules() {
  3882. // Hook to adjust the required PHP modules in the 1-2-3 installer
  3883. $modules = $this->requiredPhpModules;
  3884. if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['requiredPhpModules'])) {
  3885. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['requiredPhpModules'] as $classData) {
  3886. $hookObject = t3lib_div::getUserObj($classData);
  3887. $modules = $hookObject->setRequiredPhpModules($modules, $this);
  3888. }
  3889. }
  3890. $this->requiredPhpModules = $modules;
  3891. $result = array();
  3892. foreach ($this->requiredPhpModules as $module) {
  3893. if (is_array($module)) {
  3894. $detectedSubmodules = FALSE;
  3895. foreach ($module as $submodule) {
  3896. if (extension_loaded($submodule)) {
  3897. $detectedSubmodules = TRUE;
  3898. }
  3899. }
  3900. if ($detectedSubmodules === FALSE) {
  3901. $result[] = 'one of: (' . implode(', ', $module) . ')';
  3902. }
  3903. } else {
  3904. if (!extension_loaded($module)) {
  3905. $result[] = $module;
  3906. }
  3907. }
  3908. }
  3909. return $result;
  3910. }
  3911. /*****************************************
  3912. *
  3913. * ABOUT the isXXX functions.
  3914. *
  3915. * I had a very real experience that these checks DID NOT fail eg PNG support if it didn't exist!
  3916. * So first (1) we check if the functions are there. If they ARE we are going to make further investigations (2) by creating an actual image.
  3917. * And if THAT succeeds also, then we can be certain of the support!
  3918. */
  3919. /**
  3920. * Check if GD module is available by checking the function imagecreate
  3921. *
  3922. * @return boolean TRUE if GD is available
  3923. */
  3924. function isGD() {
  3925. if (function_exists('imagecreatetruecolor')) {
  3926. if (@imagecreatetruecolor(50, 100)) {
  3927. return 1;
  3928. }
  3929. }
  3930. return 0;
  3931. }
  3932. /**
  3933. * Check if GIF functions are available
  3934. *
  3935. * @return boolean TRUE if GIF functions are available
  3936. */
  3937. function isGIF() {
  3938. // If GIF-functions exists, also do a real test of them:
  3939. if (function_exists('imagecreatefromgif') && function_exists('imagegif') && ($this->ImageTypes() & IMG_GIF)) {
  3940. $im = @imagecreatefromgif(t3lib_extMgm::extPath('install').'imgs/jesus.gif');
  3941. return ($im ? 1 : 0);
  3942. }
  3943. }
  3944. /**
  3945. * Check if JPG functions are available
  3946. *
  3947. * @return boolean TRUE if JPEG functions are available
  3948. */
  3949. function isJPG() {
  3950. if (function_exists('imagecreatefromjpeg') && function_exists('imagejpeg') && ($this->ImageTypes() & IMG_JPG)) {
  3951. return 1;
  3952. }
  3953. }
  3954. /**
  3955. * Check if PNG functions are available
  3956. *
  3957. * @return boolean TRUE if PNG functions are available
  3958. */
  3959. function isPNG() {
  3960. if (function_exists('imagecreatefrompng') && function_exists('imagepng') && ($this->ImageTypes() & IMG_PNG)) {
  3961. $im = imagecreatefrompng(t3lib_extMgm::extPath('install').'imgs/jesus.png');
  3962. return ($im ? 1 : 0);
  3963. }
  3964. }
  3965. /**
  3966. * Return the image types supported by this PHP build
  3967. *
  3968. * @return integer A bit-field corresponding to the image formats supported by the version of GD linked into PHP. The following bits are returned, IMG_GIF | IMG_JPG | IMG_PNG | IMG_WBMP | IMG_XPM.
  3969. */
  3970. function ImageTypes() {
  3971. return imagetypes();
  3972. }
  3973. /**
  3974. * Returns general information about GDlib
  3975. *
  3976. * @return string HTML with GD lib information
  3977. */
  3978. function getGDSoftwareInfo() {
  3979. return '
  3980. <p>
  3981. You can get GDLib in the PNG version from
  3982. <a href="http://www.libgd.org/">http://www.libgd.org/</a>
  3983. <br />
  3984. FreeType is for download at
  3985. <a href="http://www.freetype.org/">http://www.freetype.org/</a>
  3986. <br />
  3987. Generally, TYPO3 packages are listed at
  3988. <a href="' . TYPO3_URL_DOWNLOAD . '">' . TYPO3_URL_DOWNLOAD . '</a>
  3989. </p>
  3990. ';
  3991. }
  3992. /**
  3993. * Returns general information about configuration of TYPO3.
  3994. *
  3995. * @return string HTML with the general information
  3996. */
  3997. function generallyAboutConfiguration() {
  3998. return '
  3999. <p>
  4000. Local configuration is done by overriding default values in the
  4001. included file, typo3conf/localconf.php. In this file you enter the
  4002. database information along with values in the global array
  4003. TYPO3_CONF_VARS.
  4004. <br />
  4005. The options in the TYPO3_CONF_VARS array and how to use it for your
  4006. own purposes is discussed in the base configuration file,
  4007. t3lib/stddb/DefaultSettings.php. This file sets up the default values and
  4008. subsequently includes the localconf.php file in which you can then
  4009. override values.
  4010. <br />
  4011. See this page for <a href="' . TYPO3_URL_SYSTEMREQUIREMENTS . '">more
  4012. information about system requirements.</a>
  4013. </p>';
  4014. }
  4015. /**********************
  4016. *
  4017. * IMAGE processing
  4018. *
  4019. **********************/
  4020. /**
  4021. * jesus.TIF: IBM/LZW
  4022. * jesus.GIF: Save for web, 32 colors
  4023. * jesus.JPG: Save for web, 30 quality
  4024. * jesus.PNG: Save for web, PNG-24
  4025. * jesus.tga 24 bit TGA file
  4026. * jesus.pcx
  4027. * jesus.bmp 24 bit BMP file
  4028. * jesus_ps6.PDF: PDF w/layers and vector data
  4029. * typo3logo.ai: Illustrator 8 file
  4030. * pdf_from_imagemagick.PDF PDF-file made by Acrobat Distiller from InDesign PS-file
  4031. *
  4032. *
  4033. * Imagemagick
  4034. * - Read formats
  4035. * - Write png, gif, jpg
  4036. *
  4037. * Problems may arise from the use of safe_mode (eg. png)
  4038. * In safemode you will automatically execute the program convert in the safe_mode_exec_path no matter what other path you specify
  4039. * check fileexist before anything...
  4040. *
  4041. * - compare gif size
  4042. * - scaling (by stdgraphic)
  4043. * - combining (by stdgraphic)
  4044. *
  4045. * GDlib:
  4046. * - create from:....
  4047. * - ttf text
  4048. *
  4049. * From TypoScript: (GD only, GD+IM, IM)
  4050. *
  4051. * @return void
  4052. */
  4053. function checkTheImageProcessing() {
  4054. $this->message('Image Processing', 'What is it?', '
  4055. <p>
  4056. TYPO3 is known for its ability to process images on the server.
  4057. <br />
  4058. In the backend interface (TBE) thumbnails are automatically
  4059. generated (by ImageMagick in thumbs.php) as well as icons, menu
  4060. items and pane tabs (by GDLib).
  4061. <br />
  4062. In the TypoScript enabled frontend all kinds of graphical
  4063. elements are processed. Typically images are scaled down to fit
  4064. the pages (by ImageMagick) and menu items, graphical headers and
  4065. such are generated automatically (by GDLib + ImageMagick).
  4066. <br />
  4067. In addition TYPO3 is able to handle many file formats (thanks to
  4068. ImageMagick), for example TIF, BMP, PCX, TGA, AI and PDF in
  4069. addition to the standard web formats; JPG, GIF, PNG.
  4070. </p>
  4071. <p>
  4072. In order to do this, TYPO3 uses two sets of tools:
  4073. </p>
  4074. <p>
  4075. <strong>ImageMagick / GraphicsMagick:</strong>
  4076. <br />
  4077. For conversion of non-web formats to webformats, combining
  4078. images with alpha-masks, performing image-effects like blurring
  4079. and sharpening.
  4080. <br />
  4081. ImageMagick is a collection of external programs on the server
  4082. called by the exec() function in PHP. TYPO3 uses three of these,
  4083. namely \'convert\' (converting fileformats, scaling, effects),
  4084. \'combine\'/\'composite\' (combining images with masks) and
  4085. \'identify\' (returns image information).
  4086. GraphicsMagick is an alternative to ImageMagick and can be enabled
  4087. by setting [GFX][im_version_5] to \'gm\'. This is recommended and
  4088. enabled by default.
  4089. <br />
  4090. Because ImageMagick and Graphicsmagick are external programs, two
  4091. requirements must be met: 1) The programs must be installed on the
  4092. server and working and 2) if safe_mode is enabled, the programs must
  4093. be located in the folder defined by the php.ini setting,
  4094. <em>safe_mode_exec_dir</em> (else they are not executed).
  4095. <br />
  4096. ImageMagick is available for both Windows and Unix. The current
  4097. version is 6+.
  4098. <br />
  4099. ImageMagick homepage is at <a href="http://www.imagemagick.org/">http://www.imagemagick.org/</a>
  4100. </p>
  4101. <p>
  4102. <strong>GDLib:</strong>
  4103. <br />
  4104. For drawing boxes and rendering text on images with truetype
  4105. fonts. Also used for icons, menuitems and generally the
  4106. TypoScript GIFBUILDER object is based on GDlib, but extensively
  4107. utilizing ImageMagick to process intermediate results.
  4108. <br />
  4109. GDLib is accessed through internal functions in PHP, so in this
  4110. case, you have no safe_mode problems, but you\'ll need a version
  4111. of PHP with GDLib compiled in. Also in order to use TrueType
  4112. fonts with GDLib you\'ll need FreeType compiled in as well.
  4113. <br />
  4114. </p>
  4115. ' . $this->getGDSoftwareInfo() . '
  4116. <p>
  4117. You can disable all image processing options in TYPO3
  4118. ([GFX][image_processing]=0), but that would seriously disable
  4119. TYPO3.
  4120. </p>
  4121. ');
  4122. $this->message('Image Processing', 'Verifying the image processing capabilities of your server', '
  4123. <p>
  4124. This page performs image processing and displays the result.
  4125. It\'s a thorough check that everything you\'ve configured is
  4126. working correctly.
  4127. <br />
  4128. It\'s quite simple to verify your installation; Just look down
  4129. the page, the images in pairs should look like each other. If
  4130. some images are not alike, something is wrong. You may also
  4131. notice warnings and errors if this tool found signs of any
  4132. problems.
  4133. </p>
  4134. <p>
  4135. The image to the right is the reference image (how it should be)
  4136. and to the left the image made by your server.
  4137. <br />
  4138. The reference images are made with the classic ImageMagick
  4139. install based on the 4.2.9 RPM and 5.2.3 RPM. If the version 5
  4140. flag is set, the reference images are made by the 5.2.3 RPM.
  4141. </p>
  4142. <p>
  4143. This test will work only if your ImageMagick/GDLib configuration
  4144. allows it to. The typo3temp/ folder must be writable for all the
  4145. temporary image files. They are all prefixed \'install_\' so
  4146. they are easy to recognize and delete afterwards.
  4147. </p>
  4148. ');
  4149. $im_path = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path'];
  4150. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5']=='gm') {
  4151. $im_path_version = $this->config_array['im_versions'][$im_path]['gm'];
  4152. } else {
  4153. $im_path_version = $this->config_array['im_versions'][$im_path]['convert'];
  4154. }
  4155. $im_path_lzw = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw'];
  4156. $im_path_lzw_version = $this->config_array['im_versions'][$im_path_lzw]['convert'];
  4157. $msg = '
  4158. <dl id="t3-install-imageprocessingim">
  4159. <dt>
  4160. ImageMagick enabled:
  4161. </dt>
  4162. <dd>
  4163. ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) . '
  4164. </dd>
  4165. <dt>
  4166. ImageMagick path:
  4167. </dt>
  4168. <dd>
  4169. ' . htmlspecialchars($im_path) . ' <span>(' . htmlspecialchars($im_path_version) . ')</span>
  4170. </dd>
  4171. <dt>
  4172. ImageMagick path/LZW:
  4173. </dt>
  4174. <dd>
  4175. ' . htmlspecialchars($im_path_lzw) . ' <span>(' . htmlspecialchars($im_path_lzw_version) . ')</span>
  4176. </dd>
  4177. <dt>
  4178. Version 5/GraphicsMagick flag:
  4179. </dt>
  4180. <dd>
  4181. ' . ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] ? htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5']) : '&nbsp;') . '
  4182. </dd>
  4183. </dl>
  4184. <dl id="t3-install-imageprocessingother">
  4185. <dt>
  4186. GDLib enabled:
  4187. </dt>
  4188. <dd>
  4189. ' . ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] ? htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) : '&nbsp;') . '
  4190. </dd>
  4191. <dt>
  4192. GDLib using PNG:
  4193. </dt>
  4194. <dd>
  4195. ' . ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] ? htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) : '&nbsp;') . '
  4196. </dd>
  4197. <dt>
  4198. IM5 effects enabled:
  4199. </dt>
  4200. <dd>
  4201. ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_v5effects']) . '
  4202. <span>(Blurring/Sharpening with IM 5+)</span>
  4203. </dd>
  4204. <dt>
  4205. Freetype DPI:
  4206. </dt>
  4207. <dd>
  4208. ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['TTFdpi']) . '
  4209. <span>(Should be 96 for Freetype 2)</span>
  4210. </dd>
  4211. <dt>
  4212. Mask invert:
  4213. </dt>
  4214. <dd>
  4215. ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_imvMaskState']) . '
  4216. <span>(Should be set for some IM versions approx. 5.4+)</span>
  4217. </dd>
  4218. </dl>
  4219. <dl id="t3-install-imageprocessingfileformats">
  4220. <dt>
  4221. File Formats:
  4222. </dt>
  4223. <dd>
  4224. ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']) . '
  4225. </dd>
  4226. </dl>
  4227. ';
  4228. // Various checks to detect IM/GM version mismatches
  4229. $mismatch=FALSE;
  4230. switch (strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'])) {
  4231. case 'gm':
  4232. if (doubleval($im_path_version)>=2) $mismatch=TRUE;
  4233. break;
  4234. default:
  4235. if (($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] ? TRUE : FALSE) != (doubleval($im_path_version) >= 6)) {
  4236. $mismatch = TRUE;
  4237. }
  4238. break;
  4239. }
  4240. if ($mismatch) {
  4241. $msg .= '
  4242. <p>
  4243. Warning: Mismatch between the version of ImageMagick' .
  4244. ' (' . htmlspecialchars($im_path_version) . ') and the configuration of ' .
  4245. '[GFX][im_version_5] (' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5']) . ')
  4246. </p>
  4247. ';
  4248. $etype=2;
  4249. } else $etype=1;
  4250. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5']=='gm') {
  4251. $msg = str_replace('ImageMagick', 'GraphicsMagick', $msg);
  4252. }
  4253. $this->message('Image Processing', 'Current configuration', $msg, $etype);
  4254. if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['image_processing']) {
  4255. $this->message('Image Processing', 'Image Processing disabled!', '
  4256. <p>
  4257. Image Processing is disabled by the config flag
  4258. [GFX][image_processing] set to FALSE (zero)
  4259. </p>
  4260. ', 2);
  4261. $this->output($this->outputWrapper($this->printAll()));
  4262. return;
  4263. }
  4264. if (!$this->config_array['dir_typo3temp']) {
  4265. $this->message('Image Processing', 'typo3temp/ not writable!', '
  4266. <p>
  4267. You must make typo3temp/ write enabled before you can
  4268. proceed with this test.
  4269. </p>
  4270. ', 2);
  4271. $this->output($this->outputWrapper($this->printAll()));
  4272. return;
  4273. }
  4274. $msg = '
  4275. <p>
  4276. <a id="testmenu"></a>
  4277. Click each of these links in turn to test a topic.
  4278. <strong>
  4279. Please be aware that each test may take several seconds!
  4280. </strong>:
  4281. </p>
  4282. ' . $this->imagemenu();
  4283. $this->message('Image Processing', 'Testmenu', $msg, '');
  4284. $parseStart = t3lib_div::milliseconds();
  4285. $imageProc = t3lib_div::makeInstance('t3lib_stdGraphic');
  4286. $imageProc->init();
  4287. $imageProc->tempPath = $this->typo3temp_path;
  4288. $imageProc->dontCheckForExistingTempFile=1;
  4289. $imageProc->filenamePrefix='install_';
  4290. $imageProc->dontCompress=1;
  4291. $imageProc->alternativeOutputKey='TYPO3_INSTALL_SCRIPT';
  4292. $imageProc->noFramePrepended=$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noFramePrepended'];
  4293. // Very temporary!!!
  4294. $imageProc->dontUnlinkTempFiles=0;
  4295. $imActive = ($this->config_array['im'] && $im_path);
  4296. $gdActive = ($this->config_array['gd'] && $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']);
  4297. switch($this->INSTALL['images_type']) {
  4298. case 'read':
  4299. $refParseTime='5600'; // 4.2.9
  4300. $refParseTime='3300'; // 5.2.3
  4301. $headCode = 'Reading and converting images';
  4302. $this->message($headCode, 'Supported file formats', '
  4303. <p>
  4304. This verifies that your ImageMagick installation is able
  4305. to read the nine default file formats; JPG, GIF, PNG,
  4306. TIF, BMP, PCX, TGA, PDF, AI. The tool \'identify\' will
  4307. be used to read the pixeldimensions of non-web formats.
  4308. The tool \'convert\' is used to read the image and write
  4309. a temporary JPG-file
  4310. </p>
  4311. ');
  4312. if ($imActive) {
  4313. // Reading formats - writing JPG
  4314. $extArr = explode(',', 'jpg,gif,png,tif,bmp,pcx,tga');
  4315. foreach ($extArr as $ext) {
  4316. if ($this->isExtensionEnabled($ext, $headCode, 'Read ' . strtoupper($ext))) {
  4317. $imageProc->IM_commands=array();
  4318. $theFile = t3lib_extMgm::extPath('install').'imgs/jesus.'.$ext;
  4319. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4320. $imageProc->imageMagickConvert_forceFileNameBody='read_'.$ext;
  4321. $fileInfo = $imageProc->imageMagickConvert($theFile, 'jpg', '', '', '', '', '', 1);
  4322. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4323. $this->message($headCode, 'Read ' . strtoupper($ext), $result[0], $result[1]);
  4324. }
  4325. }
  4326. if ($this->isExtensionEnabled('pdf', $headCode, 'Read PDF')) {
  4327. $imageProc->IM_commands=array();
  4328. $theFile = t3lib_extMgm::extPath('install').'imgs/pdf_from_imagemagick.pdf';
  4329. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4330. $imageProc->imageMagickConvert_forceFileNameBody='read_pdf';
  4331. $fileInfo = $imageProc->imageMagickConvert($theFile, 'jpg', '170', '', '', '', '', 1);
  4332. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4333. $this->message($headCode, 'Read PDF', $result[0], $result[1]);
  4334. }
  4335. if ($this->isExtensionEnabled('ai', $headCode, 'Read AI')) {
  4336. $imageProc->IM_commands=array();
  4337. $theFile = t3lib_extMgm::extPath('install').'imgs/typo3logotype.ai';
  4338. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4339. $imageProc->imageMagickConvert_forceFileNameBody='read_ai';
  4340. $fileInfo = $imageProc->imageMagickConvert($theFile, 'jpg', '170', '', '', '', '', 1);
  4341. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4342. $this->message($headCode, 'Read AI', $result[0], $result[1]);
  4343. }
  4344. } else {
  4345. $this->message($headCode, 'Test skipped', '
  4346. <p>
  4347. Use of ImageMagick has been disabled in the
  4348. configuration.
  4349. <br />
  4350. Refer to section \'Basic Configuration\' to change
  4351. or review you configuration settings
  4352. </p>
  4353. ', 2);
  4354. }
  4355. break;
  4356. case 'write':
  4357. $refParseTime='300';
  4358. // Writingformats - writing JPG
  4359. $headCode = 'Writing images';
  4360. $this->message($headCode, 'Writing GIF and PNG', '
  4361. <p>
  4362. This verifies that ImageMagick is able to write GIF and
  4363. PNG files.
  4364. <br />
  4365. The GIF-file is attempted compressed with LZW by the
  4366. t3lib_div::gif_compress() function.
  4367. </p>
  4368. ');
  4369. if ($imActive) {
  4370. // Writing GIF
  4371. $imageProc->IM_commands=array();
  4372. $theFile = t3lib_extMgm::extPath('install').'imgs/jesus.gif';
  4373. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4374. $imageProc->imageMagickConvert_forceFileNameBody='write_gif';
  4375. $fileInfo = $imageProc->imageMagickConvert($theFile, 'gif', '', '', '', '', '', 1);
  4376. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress']) {
  4377. clearstatcache();
  4378. $prevSize=t3lib_div::formatSize(@filesize($fileInfo[3]));
  4379. $returnCode = t3lib_div::gif_compress($fileInfo[3], '');
  4380. clearstatcache();
  4381. $curSize=t3lib_div::formatSize(@filesize($fileInfo[3]));
  4382. $note = array('Note on gif_compress() function:', "The 'gif_compress' method used was '".$returnCode."'.<br />Previous filesize: ".$prevSize.'. Current filesize:'.$curSize);
  4383. } else $note=array('Note on gif_compress() function:', '<em>Not used! Disabled by [GFX][gif_compress]</em>');
  4384. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands, $note);
  4385. $this->message($headCode, 'Write GIF', $result[0], $result[1]);
  4386. // Writing PNG
  4387. $imageProc->IM_commands=array();
  4388. $theFile = t3lib_extMgm::extPath('install').'imgs/jesus.gif';
  4389. $imageProc->imageMagickConvert_forceFileNameBody='write_png';
  4390. $fileInfo = $imageProc->imageMagickConvert($theFile, 'png', '', '', '', '', '', 1);
  4391. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4392. $this->message($headCode, 'Write PNG', $result[0], $result[1]);
  4393. } else {
  4394. $this->message($headCode, 'Test skipped', '
  4395. <p>
  4396. Use of ImageMagick has been disabled in the
  4397. configuration.
  4398. <br />
  4399. Refer to section \'Basic Configuration\' to change
  4400. or review you configuration settings
  4401. </p>
  4402. ', 2);
  4403. }
  4404. break;
  4405. case 'scaling':
  4406. $refParseTime='650';
  4407. // Scaling
  4408. $headCode = 'Scaling images';
  4409. $this->message($headCode, 'Scaling transparent images', '
  4410. <p>
  4411. This shows how ImageMagick reacts when scaling
  4412. transparent GIF and PNG files.
  4413. </p>
  4414. ');
  4415. if ($imActive) {
  4416. // Scaling transparent image
  4417. $imageProc->IM_commands=array();
  4418. $theFile = t3lib_extMgm::extPath('install').'imgs/jesus2_transp.gif';
  4419. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4420. $imageProc->imageMagickConvert_forceFileNameBody='scale_gif';
  4421. $fileInfo = $imageProc->imageMagickConvert($theFile, 'gif', '150', '', '', '', '', 1);
  4422. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress']) {
  4423. clearstatcache();
  4424. $prevSize=t3lib_div::formatSize(@filesize($fileInfo[3]));
  4425. $returnCode = t3lib_div::gif_compress($fileInfo[3], '');
  4426. clearstatcache();
  4427. $curSize=t3lib_div::formatSize(@filesize($fileInfo[3]));
  4428. $note = array('Note on gif_compress() function:', "The 'gif_compress' method used was '".$returnCode."'.<br />Previous filesize: ".$prevSize.'. Current filesize:'.$curSize);
  4429. } else $note=array('Note on gif_compress() function:', '<em>Not used! Disabled by [GFX][gif_compress]</em>');
  4430. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands, $note);
  4431. $this->message($headCode, 'GIF to GIF, 150 pixels wide', $result[0], $result[1]);
  4432. $imageProc->IM_commands=array();
  4433. $theFile = t3lib_extMgm::extPath('install').'imgs/jesus2_transp.png';
  4434. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4435. $imageProc->imageMagickConvert_forceFileNameBody='scale_png';
  4436. $fileInfo = $imageProc->imageMagickConvert($theFile, 'png', '150', '', '', '', '', 1);
  4437. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4438. $this->message($headCode, 'PNG to PNG, 150 pixels wide', $result[0], $result[1]);
  4439. $imageProc->IM_commands=array();
  4440. $theFile = t3lib_extMgm::extPath('install').'imgs/jesus2_transp.gif';
  4441. if (!@is_file($theFile)) die('Error: '.$theFile.' was not a file');
  4442. $imageProc->imageMagickConvert_forceFileNameBody='scale_jpg';
  4443. $fileInfo = $imageProc->imageMagickConvert($theFile, 'jpg', '150', '', '', '', '', 1);
  4444. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4445. $this->message($headCode, 'GIF to JPG, 150 pixels wide', $result[0], $result[1]);
  4446. } else {
  4447. $this->message($headCode, 'Test skipped', '
  4448. <p>
  4449. Use of ImageMagick has been disabled in the
  4450. configuration.
  4451. <br />
  4452. Refer to section \'Basic Configuration\' to change
  4453. or review you configuration settings
  4454. </p>
  4455. ', 2);
  4456. }
  4457. break;
  4458. case 'combining':
  4459. $refParseTime='150'; // 4.2.9
  4460. $refParseTime='250'; // 5.2.3
  4461. // Combine
  4462. $headCode = 'Combining images';
  4463. $this->message($headCode, 'Combining images', '
  4464. <p>
  4465. This verifies that the ImageMagick tool,
  4466. \'combine\'/\'composite\', is able to combine two images
  4467. through a grayscale mask.
  4468. <br />
  4469. If the masking seems to work but inverted, that just
  4470. means you\'ll have to make sure the invert flag is set
  4471. (some combination of im_negate_mask/im_imvMaskState)
  4472. </p>
  4473. ');
  4474. if ($imActive) {
  4475. $imageProc->IM_commands=array();
  4476. $input = t3lib_extMgm::extPath('install').'imgs/greenback.gif';
  4477. $overlay = t3lib_extMgm::extPath('install').'imgs/jesus.jpg';
  4478. $mask = t3lib_extMgm::extPath('install').'imgs/blackwhite_mask.gif';
  4479. if (!@is_file($input)) die('Error: '.$input.' was not a file');
  4480. if (!@is_file($overlay)) die('Error: '.$overlay.' was not a file');
  4481. if (!@is_file($mask)) die('Error: '.$mask.' was not a file');
  4482. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5($imageProc->alternativeOutputKey.'combine1').'.jpg';
  4483. $imageProc->combineExec($input, $overlay, $mask, $output, TRUE);
  4484. $fileInfo = $imageProc->getImageDimensions($output);
  4485. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4486. $this->message($headCode, 'Combine using a GIF mask with only black and white', $result[0], $result[1]);
  4487. // Combine
  4488. $imageProc->IM_commands=array();
  4489. $input = t3lib_extMgm::extPath('install').'imgs/combine_back.jpg';
  4490. $overlay = t3lib_extMgm::extPath('install').'imgs/jesus.jpg';
  4491. $mask = t3lib_extMgm::extPath('install').'imgs/combine_mask.jpg';
  4492. if (!@is_file($input)) die('Error: '.$input.' was not a file');
  4493. if (!@is_file($overlay)) die('Error: '.$overlay.' was not a file');
  4494. if (!@is_file($mask)) die('Error: '.$mask.' was not a file');
  4495. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5($imageProc->alternativeOutputKey.'combine2').'.jpg';
  4496. $imageProc->combineExec($input, $overlay, $mask, $output, TRUE);
  4497. $fileInfo = $imageProc->getImageDimensions($output);
  4498. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4499. $this->message($headCode, 'Combine using a JPG mask with graylevels', $result[0], $result[1]);
  4500. } else {
  4501. $this->message($headCode, 'Test skipped', '
  4502. <p>
  4503. Use of ImageMagick has been disabled in the
  4504. configuration.
  4505. <br />
  4506. Refer to section \'Basic Configuration\' to change
  4507. or review you configuration settings
  4508. </p>
  4509. ', 2);
  4510. }
  4511. break;
  4512. case 'gdlib':
  4513. // GIF / 4.2.9 / LZW (5.2.3)
  4514. $refParseTime='1800';
  4515. // PNG / 4.2.9 / LZW (5.2.3)
  4516. $refParseTime='2700';
  4517. // GIF / 5.2.3 / LZW (5.2.3)
  4518. $refParseTime='1600';
  4519. // GDLibrary
  4520. $headCode = 'GDLib';
  4521. $this->message($headCode, 'Testing GDLib', '
  4522. <p>
  4523. This verifies that the GDLib installation works properly.
  4524. </p>
  4525. ');
  4526. if ($gdActive) {
  4527. // GD with box
  4528. $imageProc->IM_commands=array();
  4529. $im = imagecreatetruecolor(170, 136);
  4530. $Bcolor = ImageColorAllocate ($im, 0, 0, 0);
  4531. ImageFilledRectangle($im, 0, 0, 170, 136, $Bcolor);
  4532. $workArea=array(0, 0, 170, 136);
  4533. $conf=array(
  4534. 'dimensions' => '10,50,150,36',
  4535. 'color' => 'olive'
  4536. );
  4537. $imageProc->makeBox($im, $conf, $workArea);
  4538. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5('GDbox').'.'.$imageProc->gifExtension;
  4539. $imageProc->ImageWrite($im, $output);
  4540. $fileInfo = $imageProc->getImageDimensions($output);
  4541. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4542. $this->message($headCode, 'Create simple image', $result[0], $result[1]);
  4543. // GD from image with box
  4544. $imageProc->IM_commands=array();
  4545. $input = t3lib_extMgm::extPath('install').'imgs/jesus.'.$imageProc->gifExtension;
  4546. if (!@is_file($input)) die('Error: '.$input.' was not a file');
  4547. $im = $imageProc->imageCreateFromFile($input);
  4548. $workArea=array(0, 0, 170, 136);
  4549. $conf=array();
  4550. $conf['dimensions']='10,50,150,36';
  4551. $conf['color']='olive';
  4552. $imageProc->makeBox($im, $conf, $workArea);
  4553. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5('GDfromImage+box').'.'.$imageProc->gifExtension;
  4554. $imageProc->ImageWrite($im, $output);
  4555. $fileInfo = $imageProc->getImageDimensions($output);
  4556. $GDWithBox_filesize = @filesize($output);
  4557. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4558. $this->message($headCode, 'Create image from file', $result[0], $result[1]);
  4559. // GD with text
  4560. $imageProc->IM_commands=array();
  4561. $im = imagecreatetruecolor(170, 136);
  4562. $Bcolor = ImageColorAllocate ($im, 128, 128, 150);
  4563. ImageFilledRectangle($im, 0, 0, 170, 136, $Bcolor);
  4564. $workArea=array(0, 0, 170, 136);
  4565. $conf=array(
  4566. 'iterations' => 1,
  4567. 'angle' => 0,
  4568. 'antiAlias' => 1,
  4569. 'text' => 'HELLO WORLD',
  4570. 'fontColor' => '#003366',
  4571. 'fontSize' => 18,
  4572. 'fontFile' => $this->backPath.'../t3lib/fonts/vera.ttf',
  4573. 'offset' => '17,40'
  4574. );
  4575. $conf['BBOX'] = $imageProc->calcBBox($conf);
  4576. $imageProc->makeText($im, $conf, $workArea);
  4577. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5('GDwithText').'.'.$imageProc->gifExtension;
  4578. $imageProc->ImageWrite($im, $output);
  4579. $fileInfo = $imageProc->getImageDimensions($output);
  4580. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands);
  4581. $this->message($headCode, 'Render text with TrueType font', $result[0], $result[1]);
  4582. if ($imActive) {
  4583. // extension: GD with text, niceText
  4584. $conf['offset'] = '17,65';
  4585. $conf['niceText'] = 1;
  4586. $imageProc->makeText($im, $conf, $workArea);
  4587. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5('GDwithText-niceText').'.'.$imageProc->gifExtension;
  4588. $imageProc->ImageWrite($im, $output);
  4589. $fileInfo = $imageProc->getImageDimensions($output);
  4590. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands, array("Note on 'niceText':", "'niceText' is a concept that tries to improve the antialiasing of the rendered type by actually rendering the textstring in double size on a black/white mask, downscaling the mask and masking the text onto the image through this mask. This involves ImageMagick 'combine'/'composite' and 'convert'."));
  4591. $this->message($headCode, 'Render text with TrueType font using \'niceText\' option', '
  4592. <p>
  4593. (If the image has another background color than
  4594. the image above (eg. dark background color with
  4595. light text) then you will have to set
  4596. TYPO3_CONF_VARS[GFX][im_imvMaskState]=1)
  4597. </p>
  4598. ' . $result[0], $result[1]);
  4599. } else {
  4600. $this->message($headCode, 'Render text with TrueType font using \'niceText\' option', '
  4601. <p>
  4602. <strong>Test is skipped!</strong>
  4603. </p>
  4604. <p>
  4605. Use of ImageMagick has been disabled in the
  4606. configuration. ImageMagick is needed to generate
  4607. text with the niceText option.
  4608. <br />
  4609. Refer to section \'Basic Configuration\' to
  4610. change or review you configuration settings
  4611. </p>
  4612. ', 2);
  4613. }
  4614. if ($imActive) {
  4615. // extension: GD with text, niceText AND shadow
  4616. $conf['offset'] = '17,90';
  4617. $conf['niceText'] = 1;
  4618. $conf['shadow.'] = array(
  4619. 'offset'=>'2,2',
  4620. 'blur' => $imageProc->V5_EFFECTS ? '20' : '90',
  4621. 'opacity' => '50',
  4622. 'color' => 'black'
  4623. );
  4624. $imageProc->makeShadow($im, $conf['shadow.'], $workArea, $conf);
  4625. $imageProc->makeText($im, $conf, $workArea);
  4626. $output = $imageProc->tempPath.$imageProc->filenamePrefix.t3lib_div::shortMD5('GDwithText-niceText-shadow').'.'.$imageProc->gifExtension;
  4627. $imageProc->ImageWrite($im, $output);
  4628. $fileInfo = $imageProc->getImageDimensions($output);
  4629. $result = $this->displayTwinImage($fileInfo[3], $imageProc->IM_commands, array('Note on drop shadows:', 'Drop shadows are done by using ImageMagick to blur a mask through which the drop shadow is generated. The blurring of the mask only works in ImageMagick 4.2.9 and <em>not</em> ImageMagick 5 - which is why you may see a hard and not soft shadow.'));
  4630. $this->message($headCode, 'Render \'niceText\' with a shadow under', '
  4631. <p>
  4632. (This test makes sense only if the above test
  4633. had a correct output. But if so, you may not see
  4634. a soft dropshadow from the third text string as
  4635. you should. In that case you are most likely
  4636. using ImageMagick 5 and should set the flag
  4637. TYPO3_CONF_VARS[GFX][im_v5effects]. However this
  4638. may cost server performance!
  4639. </p>
  4640. ' . $result[0], $result[1]);
  4641. } else {
  4642. $this->message($headCode, 'Render \'niceText\' with a shadow under', '
  4643. <p>
  4644. <strong>Test is skipped!</strong>
  4645. </p>
  4646. <p>
  4647. Use of ImageMagick has been disabled in the
  4648. configuration. ImageMagick is needed to generate
  4649. shadows.
  4650. <br />
  4651. Refer to section \'Basic Configuration\' to
  4652. change or review you configuration settings
  4653. </p>
  4654. ', 2);
  4655. }
  4656. if ($imageProc->gifExtension=='gif') {
  4657. $buffer=20;
  4658. $assess = "This assessment is based on the filesize from 'Create image from file' test, which were ".$GDWithBox_filesize.' bytes';
  4659. $goodNews = "If the image was LZW compressed you would expect to have a size of less than 9000 bytes. If you open the image with Photoshop and saves it from Photoshop, you'll a filesize like that.<br />The good news is (hopefully) that your [GFX][im_path_lzw] path is correctly set so the gif_compress() function will take care of the compression for you!";
  4660. if ($GDWithBox_filesize<8784+$buffer) {
  4661. $msg = '
  4662. <p>
  4663. <strong>
  4664. Your GDLib appears to have LZW compression!
  4665. </strong>
  4666. <br />
  4667. This assessment is based on the filesize
  4668. from \'Create image from file\' test, which
  4669. were ' . $GDWithBox_filesize . ' bytes.
  4670. <br />
  4671. This is a real advantage for you because you
  4672. don\'t need to use ImageMagick for LZW
  4673. compressing. In order to make sure that
  4674. GDLib is used,
  4675. <strong>
  4676. please set the config option
  4677. [GFX][im_path_lzw] to an empty string!
  4678. </strong>
  4679. <br />
  4680. When you disable the use of ImageMagick for
  4681. LZW compressing, you\'ll see that the
  4682. gif_compress() function has a return code of
  4683. \'GD\' (for GDLib) instead of \'IM\' (for
  4684. ImageMagick)
  4685. </p>
  4686. ';
  4687. } elseif ($GDWithBox_filesize>19000) {
  4688. $msg = '
  4689. <p>
  4690. <strong>
  4691. Your GDLib appears to have no
  4692. compression at all!
  4693. </strong>
  4694. <br />
  4695. ' . $assess . '
  4696. <br />
  4697. ' . $goodNews . '
  4698. </p>
  4699. ';
  4700. } else {
  4701. $msg = '
  4702. <p>
  4703. Your GDLib appears to have RLE compression
  4704. <br />
  4705. ' . $assess . '
  4706. <br />
  4707. ' . $goodNews . '
  4708. </p>
  4709. ';
  4710. }
  4711. $this->message($headCode, 'GIF compressing in GDLib', '
  4712. ' . $msg . '
  4713. ', 1);
  4714. }
  4715. } else {
  4716. $this->message($headCode, 'Test skipped', '
  4717. <p>
  4718. Use of GDLib has been disabled in the configuration.
  4719. <br />
  4720. Refer to section \'Basic Configuration\' to change
  4721. or review you configuration settings
  4722. </p>
  4723. ', 2);
  4724. }
  4725. break;
  4726. }
  4727. if ($this->INSTALL['images_type']) {
  4728. // End info
  4729. if ($this->fatalError) {
  4730. $this->message('Info', 'Errors', '
  4731. <p>
  4732. It seems that you had some fatal errors in this test.
  4733. Please make sure that your ImageMagick and GDLib
  4734. settings are correct. Refer to the
  4735. \'Basic Configuration\' section for more information and
  4736. debugging of your settings.
  4737. </p>
  4738. ');
  4739. }
  4740. $parseMS = t3lib_div::milliseconds() - $parseStart;
  4741. $this->message('Info', 'Parsetime', '
  4742. <p>
  4743. ' . $parseMS . ' ms
  4744. </p>
  4745. ');
  4746. }
  4747. $this->output($this->outputWrapper($this->printAll()));
  4748. }
  4749. /**
  4750. * Check if image file extension is enabled
  4751. * Adds error message to the message array
  4752. *
  4753. * @param string $ext The image file extension
  4754. * @param string $headCode The header for the message
  4755. * @param string $short The short description for the message
  4756. * @return boolean TRUE if extension is enabled
  4757. */
  4758. function isExtensionEnabled($ext, $headCode, $short) {
  4759. if (!t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $ext)) {
  4760. $this->message($headCode, $short, '
  4761. <p>
  4762. Skipped - extension not in the list of allowed extensions
  4763. ([GFX][imagefile_ext]).
  4764. </p>
  4765. ', 1);
  4766. } else {
  4767. return 1;
  4768. }
  4769. }
  4770. /**
  4771. * Generate the HTML after reading and converting images
  4772. * Displays the verification and the converted image if succeeded
  4773. * Adds error messages if needed
  4774. *
  4775. * @param string $imageFile The file name of the converted image
  4776. * @param array $IMcommands The ImageMagick commands used
  4777. * @param string $note Additional note for image operation
  4778. * @return array Contains content and highest error level
  4779. */
  4780. function displayTwinImage ($imageFile, $IMcommands=array(), $note='') {
  4781. // Get the template file
  4782. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'DisplayTwinImage.html');
  4783. // Get the template part from the file
  4784. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  4785. $content = '';
  4786. $errorLevels=array(-1);
  4787. if ($imageFile) {
  4788. // Get the subpart for the images
  4789. $imageSubpart = t3lib_parsehtml::getSubpart($template, '###IMAGE###');
  4790. $verifyFile = t3lib_extMgm::extPath('install').'verify_imgs/'.basename($imageFile);
  4791. $destImg = @getImageSize($imageFile);
  4792. $destImgCode ='<img src="'.$this->backPath.'../'.substr($imageFile, strlen(PATH_site)).'" '.$destImg[3].'>';
  4793. $verifyImg = @getImageSize($verifyFile);
  4794. $verifyImgCode = '<img src="'.$this->backPath.t3lib_extMgm::extRelPath('install').'verify_imgs/'.basename($verifyFile).'" '.$verifyImg[3].'>';
  4795. clearstatcache();
  4796. $destImg['filesize'] = @filesize($imageFile);
  4797. clearstatcache();
  4798. $verifyImg['filesize'] = @filesize($verifyFile);
  4799. // Define the markers content
  4800. $imageMarkers = array(
  4801. 'destWidth' => $destImg[0],
  4802. 'destHeight' => $destImg[1],
  4803. 'destUrl' => $this->backPath . '../' . substr($imageFile, strlen(PATH_site)),
  4804. 'verifyWidth' => $verifyImg[0],
  4805. 'verifyHeight' => $verifyImg[1],
  4806. 'verifyUrl' => $this->backPath . t3lib_extMgm::extRelPath('install') . 'verify_imgs/' . basename($verifyFile),
  4807. 'yourServer' => 'Your server:',
  4808. 'yourServerInformation' => t3lib_div::formatSize($destImg['filesize']) . ', ' . $destImg[0] . 'x' . $destImg[1] . ' pixels',
  4809. 'reference' => 'Reference:',
  4810. 'referenceInformation' => t3lib_div::formatSize($verifyImg['filesize']) . ', ' . $verifyImg[0] . 'x' . $verifyImg[1] . ' pixels'
  4811. );
  4812. if ($destImg[0]!=$verifyImg[0] || $destImg[1]!=$verifyImg[1]) {
  4813. // Get the subpart for the different pixel dimensions message
  4814. $differentPixelDimensionsSubpart = t3lib_parsehtml::getSubpart($imageSubpart, '###DIFFERENTPIXELDIMENSIONS###');
  4815. // Define the markers content
  4816. $differentPixelDimensionsMarkers = array(
  4817. 'message' => 'Pixel dimension are not equal!'
  4818. );
  4819. // Fill the markers in the subpart
  4820. $differentPixelDimensionsSubpart = t3lib_parsehtml::substituteMarkerArray(
  4821. $differentPixelDimensionsSubpart,
  4822. $differentPixelDimensionsMarkers,
  4823. '###|###',
  4824. TRUE,
  4825. FALSE
  4826. );
  4827. $errorLevels[]=2;
  4828. }
  4829. // Substitute the subpart for different pixel dimensions message
  4830. $imageSubpart = t3lib_parsehtml::substituteSubpart(
  4831. $imageSubpart,
  4832. '###DIFFERENTPIXELDIMENSIONS###',
  4833. $differentPixelDimensionsSubpart
  4834. );
  4835. if ($note) {
  4836. // Get the subpart for the note
  4837. $noteSubpart = t3lib_parsehtml::getSubpart($imageSubpart, '###NOTE###');
  4838. // Define the markers content
  4839. $noteMarkers = array(
  4840. 'message' => $note[0],
  4841. 'label' => $note[1]
  4842. );
  4843. // Fill the markers in the subpart
  4844. $noteSubpart = t3lib_parsehtml::substituteMarkerArray(
  4845. $noteSubpart,
  4846. $noteMarkers,
  4847. '###|###',
  4848. TRUE,
  4849. FALSE
  4850. );
  4851. }
  4852. // Substitute the subpart for the note
  4853. $imageSubpart = t3lib_parsehtml::substituteSubpart(
  4854. $imageSubpart,
  4855. '###NOTE###',
  4856. $noteSubpart
  4857. );
  4858. if ($this->dumpImCommands && count($IMcommands)) {
  4859. $commands = $this->formatImCmds($IMcommands);
  4860. // Get the subpart for the ImageMagick commands
  4861. $imCommandsSubpart = t3lib_parsehtml::getSubpart($imageSubpart, '###IMCOMMANDS###');
  4862. // Define the markers content
  4863. $imCommandsMarkers = array(
  4864. 'message' => 'ImageMagick commands executed:',
  4865. 'rows' => t3lib_utility_Math::forceIntegerInRange(count($commands), 2, 10),
  4866. 'commands' => htmlspecialchars(implode(LF, $commands))
  4867. );
  4868. // Fill the markers in the subpart
  4869. $imCommandsSubpart = t3lib_parsehtml::substituteMarkerArray(
  4870. $imCommandsSubpart,
  4871. $imCommandsMarkers,
  4872. '###|###',
  4873. TRUE,
  4874. FALSE
  4875. );
  4876. }
  4877. // Substitute the subpart for the ImageMagick commands
  4878. $imageSubpart = t3lib_parsehtml::substituteSubpart(
  4879. $imageSubpart,
  4880. '###IMCOMMANDS###',
  4881. $imCommandsSubpart
  4882. );
  4883. // Fill the markers
  4884. $imageSubpart = t3lib_parsehtml::substituteMarkerArray(
  4885. $imageSubpart,
  4886. $imageMarkers,
  4887. '###|###',
  4888. TRUE,
  4889. FALSE
  4890. );
  4891. } else {
  4892. // Get the subpart when no image has been generated
  4893. $noImageSubpart = t3lib_parsehtml::getSubpart($template, '###NOIMAGE###');
  4894. $commands = $this->formatImCmds($IMcommands);
  4895. if (count($commands)) {
  4896. // Get the subpart for the ImageMagick commands
  4897. $commandsSubpart = t3lib_parsehtml::getSubpart($noImageSubpart, '###COMMANDSAVAILABLE###');
  4898. // Define the markers content
  4899. $commandsMarkers = array(
  4900. 'rows' => t3lib_utility_Math::forceIntegerInRange(count($commands), 2, 10),
  4901. 'commands' => htmlspecialchars(implode(LF, $commands))
  4902. );
  4903. // Fill the markers in the subpart
  4904. $commandsSubpart = t3lib_parsehtml::substituteMarkerArray(
  4905. $commandsSubpart,
  4906. $commandsMarkers,
  4907. '###|###',
  4908. TRUE,
  4909. FALSE
  4910. );
  4911. }
  4912. // Substitute the subpart for the ImageMagick commands
  4913. $noImageSubpart = t3lib_parsehtml::substituteSubpart(
  4914. $noImageSubpart,
  4915. '###COMMANDSAVAILABLE###',
  4916. $commandsSubpart
  4917. );
  4918. // Define the markers content
  4919. $noImageMarkers = array(
  4920. 'message' => 'There was no result from the ImageMagick operation',
  4921. 'label' => 'Below there\'s a dump of the ImageMagick commands executed:'
  4922. );
  4923. // Fill the markers
  4924. $noImageSubpart = t3lib_parsehtml::substituteMarkerArray(
  4925. $noImageSubpart,
  4926. $noImageMarkers,
  4927. '###|###',
  4928. TRUE,
  4929. FALSE
  4930. );
  4931. $errorLevels[]=3;
  4932. }
  4933. // Substitute the subpart when image has been generated
  4934. $content = t3lib_parsehtml::substituteSubpart(
  4935. $template,
  4936. '###IMAGE###',
  4937. $imageSubpart
  4938. );
  4939. // Substitute the subpart when no image has been generated
  4940. $content = t3lib_parsehtml::substituteSubpart(
  4941. $content,
  4942. '###NOIMAGE###',
  4943. $noImageSubpart
  4944. );
  4945. return array($content, max($errorLevels));
  4946. }
  4947. /**
  4948. * Format ImageMagick commands for use in HTML
  4949. *
  4950. * @param array $arr The ImageMagick commands
  4951. * @return string The formatted commands
  4952. */
  4953. function formatImCmds($arr) {
  4954. $out = array();
  4955. if (is_array($arr)) {
  4956. foreach ($arr as $k => $v) {
  4957. $out[] = $v[1];
  4958. if ($v[2]) {
  4959. $out[]=' RETURNED: ' . $v[2];
  4960. }
  4961. }
  4962. }
  4963. return $out;
  4964. }
  4965. /**
  4966. * Generate the menu for the test menu in 'image processing'
  4967. *
  4968. * @return string The HTML for the test menu
  4969. */
  4970. function imagemenu() {
  4971. // Get the template file
  4972. $template = @file_get_contents(PATH_site . $this->templateFilePath . 'ImageMenu.html');
  4973. // Get the subpart for the menu
  4974. $menuSubPart = t3lib_parsehtml::getSubpart($template, '###MENU###');
  4975. // Get the subpart for the single item in the menu
  4976. $menuItemSubPart = t3lib_parsehtml::getSubpart($menuSubPart, '###MENUITEM###');
  4977. $menuitems = array(
  4978. 'read' => 'Reading image formats',
  4979. 'write' => 'Writing GIF and PNG',
  4980. 'scaling' => 'Scaling images',
  4981. 'combining' => 'Combining images',
  4982. 'gdlib' => 'GD library functions'
  4983. );
  4984. $c = 0;
  4985. $items = array();
  4986. foreach ($menuitems as $k => $v) {
  4987. // Define the markers content
  4988. $markers = array(
  4989. 'backgroundColor' => $this->INSTALL['images_type'] == $k ? 'activeMenu' : 'generalTableBackground',
  4990. 'url' => htmlspecialchars($this->action . '&TYPO3_INSTALL[images_type]=' . $k . '#imageMenu'),
  4991. 'item' => $v
  4992. );
  4993. // Fill the markers in the subpart
  4994. $items[] = t3lib_parsehtml::substituteMarkerArray(
  4995. $menuItemSubPart,
  4996. $markers,
  4997. '###|###',
  4998. TRUE,
  4999. FALSE
  5000. );
  5001. }
  5002. // Substitute the subpart for the single item in the menu
  5003. $menuSubPart = t3lib_parsehtml::substituteSubpart(
  5004. $menuSubPart,
  5005. '###MENUITEM###',
  5006. implode(LF, $items)
  5007. );
  5008. return $menuSubPart;
  5009. }
  5010. /**********************
  5011. *
  5012. * DATABASE analysing
  5013. *
  5014. **********************/
  5015. /**
  5016. * The Database Analyzer
  5017. *
  5018. * @return void
  5019. */
  5020. function checkTheDatabase() {
  5021. if (!$this->config_array['mysqlConnect']) {
  5022. $this->message('Database Analyser', 'Your database connection failed', '
  5023. <p>
  5024. Please go to the \'Basic Configuration\' section and correct
  5025. this problem first.
  5026. </p>
  5027. ', 2);
  5028. $this->output($this->outputWrapper($this->printAll()));
  5029. return;
  5030. }
  5031. if ($this->config_array['no_database']) {
  5032. $this->message('Database Analyser', 'No database selected', '
  5033. <p>
  5034. Please go to the \'Basic Configuration\' section and correct
  5035. this problem first.
  5036. </p>
  5037. ', 2);
  5038. $this->output($this->outputWrapper($this->printAll()));
  5039. return;
  5040. }
  5041. // Getting current tables
  5042. $whichTables=$this->sqlHandler->getListOfTables();
  5043. // Getting number of static_template records
  5044. if ($whichTables['static_template']) {
  5045. $static_template_count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'static_template');
  5046. }
  5047. $static_template_count=intval($static_template_count);
  5048. $headCode ='Database Analyser';
  5049. $this->message($headCode, 'What is it?', '
  5050. <p>
  5051. In this section you can get an overview of your currently
  5052. selected database compared to sql-files. You can also import
  5053. sql-data directly into the database or upgrade tables from
  5054. earlier versions of TYPO3.
  5055. </p>
  5056. ', 0);
  5057. $this->message($headCode, 'Connected to SQL database successfully', '
  5058. <dl id="t3-install-databaseconnected">
  5059. <dt>
  5060. Username:
  5061. </dt>
  5062. <dd>
  5063. ' . htmlspecialchars(TYPO3_db_username) . '
  5064. </dd>
  5065. <dt>
  5066. Host:
  5067. </dt>
  5068. <dd>
  5069. ' . htmlspecialchars(TYPO3_db_host) . '
  5070. </dd>
  5071. </dl>
  5072. ', -1, 1);
  5073. $this->message($headCode, 'Database', '
  5074. <p>
  5075. <strong>' . htmlspecialchars(TYPO3_db) . '</strong> is selected as database.
  5076. <br />
  5077. Has <strong>' . count($whichTables) . '</strong> tables.
  5078. </p>
  5079. ', -1, 1);
  5080. // Menu
  5081. $sql_files = array_merge(
  5082. t3lib_div::getFilesInDir(PATH_typo3conf, 'sql', 1, 1),
  5083. array()
  5084. );
  5085. $action_type = $this->INSTALL['database_type'];
  5086. $actionParts = explode('|', $action_type);
  5087. if (count($actionParts)<2) {
  5088. $action_type='';
  5089. }
  5090. // Get the template file
  5091. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckTheDatabaseMenu.html');
  5092. // Get the template part from the file
  5093. $menu = t3lib_parsehtml::getSubpart($templateFile, '###MENU###');
  5094. $menuMarkers = array(
  5095. 'action' => $this->action,
  5096. 'updateRequiredTables' => 'Update required tables',
  5097. 'compare' => 'COMPARE',
  5098. 'noticeCmpFileCurrent' => ($action_type == 'cmpFile|CURRENT_TABLES' ? ' class="notice"' : ''),
  5099. 'dumpStaticData' => 'Dump static data',
  5100. 'import' => 'IMPORT',
  5101. 'noticeImportCurrent' => ($action_type == 'import|CURRENT_STATIC' ? ' class="notice"' : ''),
  5102. 'noticeCmpTca' => ($action_type == 'cmpTCA|' ? ' class="notice"' : ''),
  5103. 'compareWithTca' => 'Compare with $TCA',
  5104. 'noticeAdminUser' => ($action_type == 'adminUser|' ? ' class="notice"' : ''),
  5105. 'createAdminUser' => 'Create "admin" user',
  5106. 'noticeUc' => ($action_type == 'UC|' ? ' class="notice"' : ''),
  5107. 'resetUserPreferences' => 'Reset user preferences',
  5108. 'noticeCache' => ($action_type == 'cache|' ? ' class="notice"' : ''),
  5109. 'clearTables' => 'Clear tables'
  5110. );
  5111. // Get the subpart for extra SQL
  5112. $extraSql = t3lib_parsehtml::getSubpart($menu, '###EXTRASQL###');
  5113. $directJump='';
  5114. $extraSqlFiles = array();
  5115. foreach ($sql_files as $k => $file) {
  5116. if ($this->mode=='123' && !count($whichTables) && strstr($file, '_testsite')) {
  5117. $directJump = $this->action.'&TYPO3_INSTALL[database_type]=import|'.rawurlencode($file);
  5118. }
  5119. $lf=t3lib_utility_Math::canBeInterpretedAsInteger($k);
  5120. $fShortName = substr($file, strlen(PATH_site));
  5121. $spec1 = $spec2 = '';
  5122. // Define the markers content
  5123. $extraSqlMarkers = array(
  5124. 'fileShortName' => $fShortName,
  5125. 'fileSize' => t3lib_div::formatSize(filesize($file)),
  5126. 'noticeCmpFile' => ($action_type == 'cmpFile|' . $file ? ' class="notice"' : ''),
  5127. 'file' => rawurlencode($file),
  5128. 'noticeImport' => ($action_type == 'import|' . $file ? ' class="notice"' : ''),
  5129. 'specs' => $spec1 . $spec2,
  5130. 'noticeView' => ($action_type == 'view|' . $file ? ' class="notice"' : ''),
  5131. 'view' => 'VIEW'
  5132. );
  5133. // Fill the markers in the subpart
  5134. $extraSqlFiles[] = t3lib_parsehtml::substituteMarkerArray(
  5135. $extraSql,
  5136. $extraSqlMarkers,
  5137. '###|###',
  5138. TRUE,
  5139. FALSE
  5140. );
  5141. }
  5142. // Substitute the subpart for extra SQL
  5143. $menu = t3lib_parsehtml::substituteSubpart(
  5144. $menu,
  5145. '###EXTRASQL###',
  5146. implode(LF, $extraSqlFiles)
  5147. );
  5148. // Fill the markers
  5149. $menu = t3lib_parsehtml::substituteMarkerArray(
  5150. $menu,
  5151. $menuMarkers,
  5152. '###|###',
  5153. TRUE,
  5154. FALSE
  5155. );
  5156. if ($directJump) {
  5157. if (!$action_type) {
  5158. $this->message($headCode, 'Menu', '
  5159. <script language="javascript" type="text/javascript">
  5160. window.location.href = "' . $directJump . '";
  5161. </script>',
  5162. 0, 1);
  5163. }
  5164. } else {
  5165. $this->message($headCode, 'Menu', '
  5166. <p>
  5167. From this menu you can select which of the available SQL
  5168. files you want to either compare or import/merge with the
  5169. existing database.
  5170. </p>
  5171. <dl id="t3-install-checkthedatabaseexplanation">
  5172. <dt>
  5173. COMPARE:
  5174. </dt>
  5175. <dd>
  5176. Compares the tables and fields of the current database
  5177. and the selected file. It also offers to \'update\' the
  5178. difference found.
  5179. </dd>
  5180. <dt>
  5181. IMPORT:
  5182. </dt>
  5183. <dd>
  5184. Imports the SQL-dump file into the current database. You
  5185. can either dump the raw file or choose which tables to
  5186. import. In any case, you\'ll see a new screen where you
  5187. must confirm the operation.
  5188. </dd>
  5189. <dt>
  5190. VIEW:
  5191. </dt>
  5192. <dd>
  5193. Shows the content of the SQL-file, limiting characters
  5194. on a single line to a reader-friendly amount.
  5195. </dd>
  5196. </dl>
  5197. <p>
  5198. The SQL-files are selected from typo3conf/ (here you can put
  5199. your own) and t3lib/stddb/ (TYPO3 distribution). The
  5200. SQL-files should be made by the <em>mysqldump</em> tool or
  5201. at least be formatted like that tool would do.
  5202. </p>
  5203. ' . $menu, 0, 1);
  5204. }
  5205. if ($action_type) {
  5206. switch($actionParts[0]) {
  5207. case 'cmpFile':
  5208. $tblFileContent='';
  5209. $hookObjects = array();
  5210. if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['checkTheDatabase'])) {
  5211. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['checkTheDatabase'] as $classData) {
  5212. /** @var $hookObject Tx_Install_Interfaces_CheckTheDatabaseHook **/
  5213. $hookObject = t3lib_div::getUserObj($classData);
  5214. if (!($hookObject instanceof Tx_Install_Interfaces_CheckTheDatabaseHook)) {
  5215. throw new UnexpectedValueException('$hookObject must implement interface Tx_Install_Interfaces_CheckTheDatabaseHook', 1315554770);
  5216. }
  5217. $hookObjects[] = $hookObject;
  5218. }
  5219. }
  5220. if (!strcmp($actionParts[1], 'CURRENT_TABLES')) {
  5221. $tblFileContent = t3lib_div::getUrl(PATH_t3lib.'stddb/tables.sql');
  5222. foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $extKey => $loadedExtConf) {
  5223. if (is_array($loadedExtConf) && $loadedExtConf['ext_tables.sql']) {
  5224. $extensionSqlContent = t3lib_div::getUrl($loadedExtConf['ext_tables.sql']);
  5225. $tblFileContent .= LF . LF . LF . LF . $extensionSqlContent;
  5226. foreach ($hookObjects as $hookObject) {
  5227. /** @var $hookObject Tx_Install_Interfaces_CheckTheDatabaseHook **/
  5228. $appendableTableDefinitions = $hookObject->appendExtensionTableDefinitions($extKey, $loadedExtConf, $extensionSqlContent, $this->sqlHandler, $this);
  5229. if ($appendableTableDefinitions) {
  5230. $tblFileContent .= $appendableTableDefinitions;
  5231. break;
  5232. }
  5233. }
  5234. }
  5235. }
  5236. } elseif (@is_file($actionParts[1])) {
  5237. $tblFileContent = t3lib_div::getUrl($actionParts[1]);
  5238. }
  5239. foreach ($hookObjects as $hookObject) {
  5240. /** @var $hookObject Tx_Install_Interfaces_CheckTheDatabaseHook **/
  5241. $appendableTableDefinitions = $hookObject->appendGlobalTableDefinitions($tblFileContent, $this->sqlHandler, $this);
  5242. if ($appendableTableDefinitions) {
  5243. $tblFileContent .= $appendableTableDefinitions;
  5244. break;
  5245. }
  5246. }
  5247. $tblFileContent .= t3lib_cache::getDatabaseTableDefinitions();
  5248. if ($tblFileContent) {
  5249. $fileContent = implode(
  5250. LF,
  5251. $this->sqlHandler->getStatementArray($tblFileContent, 1, '^CREATE TABLE ')
  5252. );
  5253. $FDfile = $this->sqlHandler->getFieldDefinitions_fileContent($fileContent);
  5254. if (!count($FDfile)) {
  5255. die ("Error: There were no 'CREATE TABLE' definitions in the provided file");
  5256. }
  5257. // Updating database...
  5258. if (is_array($this->INSTALL['database_update'])) {
  5259. $FDdb = $this->sqlHandler->getFieldDefinitions_database();
  5260. $diff = $this->sqlHandler->getDatabaseExtra($FDfile, $FDdb);
  5261. $update_statements = $this->sqlHandler->getUpdateSuggestions($diff);
  5262. $diff = $this->sqlHandler->getDatabaseExtra($FDdb, $FDfile);
  5263. $remove_statements = $this->sqlHandler->getUpdateSuggestions($diff, 'remove');
  5264. $results = array();
  5265. $results[] = $this->sqlHandler->performUpdateQueries($update_statements['clear_table'], $this->INSTALL['database_update']);
  5266. $results[] = $this->sqlHandler->performUpdateQueries($update_statements['add'], $this->INSTALL['database_update']);
  5267. $results[] = $this->sqlHandler->performUpdateQueries($update_statements['change'], $this->INSTALL['database_update']);
  5268. $results[] = $this->sqlHandler->performUpdateQueries($remove_statements['change'], $this->INSTALL['database_update']);
  5269. $results[] = $this->sqlHandler->performUpdateQueries($remove_statements['drop'], $this->INSTALL['database_update']);
  5270. $results[] = $this->sqlHandler->performUpdateQueries($update_statements['create_table'], $this->INSTALL['database_update']);
  5271. $results[] = $this->sqlHandler->performUpdateQueries($remove_statements['change_table'], $this->INSTALL['database_update']);
  5272. $results[] = $this->sqlHandler->performUpdateQueries($remove_statements['drop_table'], $this->INSTALL['database_update']);
  5273. $this->databaseUpdateErrorMessages = array();
  5274. foreach ($results as $resultSet) {
  5275. if (is_array($resultSet)) {
  5276. foreach ($resultSet as $key => $errorMessage) {
  5277. $this->databaseUpdateErrorMessages[$key] = $errorMessage;
  5278. }
  5279. }
  5280. }
  5281. }
  5282. // Init again / first time depending...
  5283. $FDdb = $this->sqlHandler->getFieldDefinitions_database();
  5284. $diff = $this->sqlHandler->getDatabaseExtra($FDfile, $FDdb);
  5285. $update_statements = $this->sqlHandler->getUpdateSuggestions($diff);
  5286. $diff = $this->sqlHandler->getDatabaseExtra($FDdb, $FDfile);
  5287. $remove_statements = $this->sqlHandler->getUpdateSuggestions($diff, 'remove');
  5288. $tLabel = 'Update database tables and fields';
  5289. if ($remove_statements || $update_statements) {
  5290. $formContent = $this->generateUpdateDatabaseForm('get_form', $update_statements, $remove_statements, $action_type);
  5291. $this->message($tLabel, 'Table and field definitions should be updated', '
  5292. <p>
  5293. There seems to be a number of differencies
  5294. between the database and the selected
  5295. SQL-file.
  5296. <br />
  5297. Please select which statements you want to
  5298. execute in order to update your database:
  5299. </p>
  5300. ' . $formContent, 2);
  5301. } else {
  5302. $formContent = $this->generateUpdateDatabaseForm('get_form', $update_statements, $remove_statements, $action_type);
  5303. $this->message($tLabel, 'Table and field definitions are OK.', '
  5304. <p>
  5305. The tables and fields in the current
  5306. database corresponds perfectly to the
  5307. database in the selected SQL-file.
  5308. </p>
  5309. ', -1);
  5310. }
  5311. }
  5312. break;
  5313. case 'cmpTCA':
  5314. $this->includeTCA();
  5315. $FDdb = $this->sqlHandler->getFieldDefinitions_database();
  5316. // Displaying configured fields which are not in the database
  5317. $tLabel='Tables and fields in $TCA, but not in database';
  5318. $cmpTCA_DB = $this->compareTCAandDatabase($GLOBALS['TCA'], $FDdb);
  5319. if (!count($cmpTCA_DB['extra'])) {
  5320. $this->message($tLabel, 'Table and field definitions OK', '
  5321. <p>
  5322. All fields and tables configured in $TCA
  5323. appeared to exist in the database as well
  5324. </p>
  5325. ', -1);
  5326. } else {
  5327. $this->message($tLabel, 'Invalid table and field definitions in $TCA!', '
  5328. <p>
  5329. There are some tables and/or fields configured
  5330. in the $TCA array which do not exist in the
  5331. database!
  5332. <br />
  5333. This will most likely cause you trouble with the
  5334. TYPO3 backend interface!
  5335. </p>
  5336. ', 3);
  5337. foreach ($cmpTCA_DB['extra'] as $tableName => $conf) {
  5338. $this->message($tLabel, $tableName, $this->displayFields($conf['fields'], 0, 'Suggested database field:'), 2);
  5339. }
  5340. }
  5341. // Displaying tables that are not setup in
  5342. $cmpDB_TCA = $this->compareDatabaseAndTCA($FDdb, $GLOBALS['TCA']);
  5343. $excludeTables='be_sessions,fe_session_data,fe_sessions';
  5344. if (TYPO3_OS=='WIN') {$excludeTables = strtolower($excludeTables);}
  5345. $excludeFields = array(
  5346. 'be_users' => 'uc,lastlogin,usergroup_cached_list',
  5347. 'fe_users' => 'uc,lastlogin,fe_cruser_id',
  5348. 'pages' => 'SYS_LASTCHANGED',
  5349. 'sys_dmail' => 'mailContent',
  5350. 'tt_board' => 'doublePostCheck',
  5351. 'tt_guest' => 'doublePostCheck',
  5352. 'tt_products' => 'ordered'
  5353. );
  5354. $tCount=0;
  5355. $fCount=0;
  5356. $tLabel='Tables from database, but not in \$TCA';
  5357. $fLabel='Fields from database, but not in \$TCA';
  5358. $this->message($tLabel);
  5359. if (is_array($cmpDB_TCA['extra'])) {
  5360. foreach ($cmpDB_TCA['extra'] as $tableName => $conf) {
  5361. if (!t3lib_div::inList($excludeTables, $tableName)
  5362. && substr($tableName, 0, 4)!='sys_'
  5363. && substr($tableName, -3)!='_mm'
  5364. && substr($tableName, 0, 6)!='index_'
  5365. && substr($tableName, 0, 6)!='cache_') {
  5366. if ($conf['whole_table']) {
  5367. $this->message($tLabel, $tableName, $this->displayFields($conf['fields']), 1);
  5368. $tCount++;
  5369. } else {
  5370. list($theContent, $fC) = $this->displaySuggestions($conf['fields'], $excludeFields[$tableName]);
  5371. $fCount+=$fC;
  5372. if ($fC) {
  5373. $this->message($fLabel, $tableName, $theContent, 1);
  5374. }
  5375. }
  5376. }
  5377. }
  5378. }
  5379. if (!$tCount) {
  5380. $this->message($tLabel, 'Correct number of tables in the database', '
  5381. <p>
  5382. There are no extra tables in the database
  5383. compared to the configured tables in the $TCA
  5384. array.
  5385. </p>
  5386. ', -1);
  5387. } else {
  5388. $this->message($tLabel, 'Extra tables in the database', '
  5389. <p>
  5390. There are some tables in the database which are
  5391. not configured in the $TCA array.
  5392. <br />
  5393. You should probably not worry about this, but
  5394. please make sure that you know what these tables
  5395. are about and why they are not configured in
  5396. $TCA.
  5397. </p>
  5398. ', 2);
  5399. }
  5400. if (!$fCount) {
  5401. $this->message($fLabel, 'Correct number of fields in the database', '
  5402. <p>
  5403. There are no additional fields in the database
  5404. tables compared to the configured fields in the
  5405. $TCA array.
  5406. </p>
  5407. ', -1);
  5408. } else {
  5409. $this->message($fLabel, 'Extra fields in the database', '
  5410. <p>
  5411. There are some additional fields the database
  5412. tables which are not configured in the $TCA
  5413. array.
  5414. <br />
  5415. You should probably not worry about this, but
  5416. please make sure that you know what these fields
  5417. are about and why they are not configured in
  5418. $TCA.
  5419. </p>
  5420. ', 2);
  5421. }
  5422. // Displaying actual and suggested field database defitions
  5423. if (is_array($cmpTCA_DB['matching'])) {
  5424. $tLabel='Comparison between database and $TCA';
  5425. $this->message($tLabel, 'Actual and suggested field definitions', '
  5426. <p>
  5427. This table shows you the suggested field
  5428. definitions which are calculated based on the
  5429. configuration in $TCA.
  5430. <br />
  5431. If the suggested value differs from the actual
  5432. current database value, you should not panic,
  5433. but simply check if the datatype of that field
  5434. is sufficient compared to the data, you want
  5435. TYPO3 to put there.
  5436. </p>
  5437. ', 0);
  5438. foreach ($cmpTCA_DB['matching'] as $tableName => $conf) {
  5439. $this->message($tLabel, $tableName, $this->displayFieldComp($conf['fields'], $FDdb[$tableName]['fields']), 1);
  5440. }
  5441. }
  5442. break;
  5443. case 'import':
  5444. $mode123Imported=0;
  5445. $tblFileContent='';
  5446. if (preg_match('/^CURRENT_/', $actionParts[1])) {
  5447. if (!strcmp($actionParts[1], 'CURRENT_TABLES') || !strcmp($actionParts[1], 'CURRENT_TABLES+STATIC')) {
  5448. $tblFileContent = t3lib_div::getUrl(PATH_t3lib.'stddb/tables.sql');
  5449. foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $loadedExtConf) {
  5450. if (is_array($loadedExtConf) && $loadedExtConf['ext_tables.sql']) {
  5451. $tblFileContent.= LF . LF . LF . LF . t3lib_div::getUrl($loadedExtConf['ext_tables.sql']);
  5452. }
  5453. }
  5454. }
  5455. if (!strcmp($actionParts[1], 'CURRENT_STATIC') || !strcmp($actionParts[1], 'CURRENT_TABLES+STATIC')) {
  5456. foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $loadedExtConf) {
  5457. if (is_array($loadedExtConf) && $loadedExtConf['ext_tables_static+adt.sql']) {
  5458. $tblFileContent.= LF . LF . LF . LF . t3lib_div::getUrl($loadedExtConf['ext_tables_static+adt.sql']);
  5459. }
  5460. }
  5461. }
  5462. $tblFileContent .= LF . LF . LF . LF . t3lib_cache::getDatabaseTableDefinitions();
  5463. } elseif (@is_file($actionParts[1])) {
  5464. $tblFileContent = t3lib_div::getUrl($actionParts[1]);
  5465. }
  5466. if ($tblFileContent) {
  5467. $tLabel='Import SQL dump';
  5468. // Getting statement array from
  5469. $statements = $this->sqlHandler->getStatementArray($tblFileContent, 1);
  5470. list($statements_table, $insertCount) = $this->sqlHandler->getCreateTables($statements, 1);
  5471. // Updating database...
  5472. if ($this->INSTALL['database_import_all']) {
  5473. $r=0;
  5474. foreach ($statements as $k=>$v) {
  5475. $res = $GLOBALS['TYPO3_DB']->admin_query($v);
  5476. $r++;
  5477. }
  5478. // Make a database comparison because some tables that are defined twice have
  5479. // not been created at this point. This applies to the "pages.*"
  5480. // fields defined in sysext/cms/ext_tables.sql for example.
  5481. $fileContent = implode(
  5482. LF,
  5483. $this->sqlHandler->getStatementArray($tblFileContent, 1, '^CREATE TABLE ')
  5484. );
  5485. $FDfile = $this->sqlHandler->getFieldDefinitions_fileContent($fileContent);
  5486. $FDdb = $this->sqlHandler->getFieldDefinitions_database();
  5487. $diff = $this->sqlHandler->getDatabaseExtra($FDfile, $FDdb);
  5488. $update_statements = $this->sqlHandler->getUpdateSuggestions($diff);
  5489. if (is_array($update_statements['add'])) {
  5490. foreach ($update_statements['add'] as $statement) {
  5491. $res = $GLOBALS['TYPO3_DB']->admin_query($statement);
  5492. }
  5493. }
  5494. if ($this->mode=='123') {
  5495. // Create default be_user admin/password
  5496. $username = 'admin';
  5497. $pass = 'password';
  5498. $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
  5499. 'uid',
  5500. 'be_users',
  5501. 'username=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($username, 'be_users')
  5502. );
  5503. if (!$count) {
  5504. $insertFields = array(
  5505. 'username' => $username,
  5506. 'password' => md5($pass),
  5507. 'admin' => 1,
  5508. 'uc' => '',
  5509. 'fileoper_perms' => 0,
  5510. 'tstamp' => $GLOBALS['EXEC_TIME'],
  5511. 'crdate' => $GLOBALS['EXEC_TIME']
  5512. );
  5513. $GLOBALS['TYPO3_DB']->exec_INSERTquery('be_users', $insertFields);
  5514. }
  5515. }
  5516. $this->message($tLabel, 'Imported ALL', '
  5517. <p>
  5518. Queries: ' . $r . '
  5519. </p>
  5520. ', 1, 1);
  5521. if (t3lib_div::_GP('goto_step')) {
  5522. $this->action.='&step='.t3lib_div::_GP('goto_step');
  5523. t3lib_utility_Http::redirect($this->action);
  5524. }
  5525. } elseif (is_array($this->INSTALL['database_import'])) {
  5526. // Traverse the tables
  5527. foreach ($this->INSTALL['database_import'] as $table => $md5str) {
  5528. if ($md5str==md5($statements_table[$table])) {
  5529. $res = $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table);
  5530. $res = $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]);
  5531. if ($insertCount[$table]) {
  5532. $statements_insert = $this->sqlHandler->getTableInsertStatements($statements, $table);
  5533. foreach ($statements_insert as $k => $v) {
  5534. $res = $GLOBALS['TYPO3_DB']->admin_query($v);
  5535. }
  5536. }
  5537. $this->message($tLabel, 'Imported \'' . $table . '\'', '
  5538. <p>
  5539. Rows: ' . $insertCount[$table] . '
  5540. </p>
  5541. ', 1, 1);
  5542. }
  5543. }
  5544. }
  5545. $mode123Imported=$this->isBasicComplete($tLabel);
  5546. if (!$mode123Imported) {
  5547. // Re-Getting current tables - may have been changed during import
  5548. $whichTables=$this->sqlHandler->getListOfTables();
  5549. if (count($statements_table)) {
  5550. reset($statements_table);
  5551. $out='';
  5552. // Get the template file
  5553. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckTheDatabaseImport.html');
  5554. // Get the template part from the file
  5555. $content = t3lib_parsehtml::getSubpart($templateFile, '###IMPORT###');
  5556. if ($this->mode!='123') {
  5557. $tables = array();
  5558. // Get the subpart for regular mode
  5559. $regularModeSubpart = t3lib_parsehtml::getSubpart($content, '###REGULARMODE###');
  5560. foreach ($statements_table as $table => $definition) {
  5561. // Get the subpart for rows
  5562. $tableSubpart = t3lib_parsehtml::getSubpart($content, '###ROWS###');
  5563. // Fill the 'table exists' part when it exists
  5564. $exist=isset($whichTables[$table]);
  5565. if ($exist) {
  5566. // Get the subpart for table exists
  5567. $existSubpart = t3lib_parsehtml::getSubpart($tableSubpart, '###EXIST###');
  5568. // Define the markers content
  5569. $existMarkers = array (
  5570. 'tableExists' => 'Table exists!',
  5571. 'backPath' => $this->backPath
  5572. );
  5573. // Fill the markers in the subpart
  5574. $existSubpart = t3lib_parsehtml::substituteMarkerArray(
  5575. $existSubpart,
  5576. $existMarkers,
  5577. '###|###',
  5578. TRUE,
  5579. FALSE
  5580. );
  5581. }
  5582. // Substitute the subpart for table exists
  5583. $tableHtml = t3lib_parsehtml::substituteSubpart(
  5584. $tableSubpart,
  5585. '###EXIST###',
  5586. $existSubpart
  5587. );
  5588. // Define the markers content
  5589. $tableMarkers = array (
  5590. 'table' => $table,
  5591. 'definition' => md5($definition),
  5592. 'count' => $insertCount[$table] ? $insertCount[$table] : '',
  5593. 'rowLabel' => $insertCount[$table] ? 'Rows: ' : '',
  5594. 'tableExists' => 'Table exists!',
  5595. 'backPath' => $this->backPath
  5596. );
  5597. // Fill the markers
  5598. $tables[] = t3lib_parsehtml::substituteMarkerArray(
  5599. $tableHtml,
  5600. $tableMarkers,
  5601. '###|###',
  5602. TRUE,
  5603. FALSE
  5604. );
  5605. }
  5606. // Substitute the subpart for the rows
  5607. $regularModeSubpart = t3lib_parsehtml::substituteSubpart(
  5608. $regularModeSubpart,
  5609. '###ROWS###',
  5610. implode(LF, $tables)
  5611. );
  5612. }
  5613. // Substitute the subpart for the regular mode
  5614. $content = t3lib_parsehtml::substituteSubpart(
  5615. $content,
  5616. '###REGULARMODE###',
  5617. $regularModeSubpart
  5618. );
  5619. // Define the markers content
  5620. $contentMarkers = array(
  5621. 'checked' => ($this->mode == '123' || t3lib_div::_GP('presetWholeTable') ? 'checked="checked"' : ''),
  5622. 'label' => 'Import the whole file \'' . basename($actionParts[1]) . '\' directly (ignores selections above)'
  5623. );
  5624. // Fill the markers
  5625. $content = t3lib_parsehtml::substituteMarkerArray(
  5626. $content,
  5627. $contentMarkers,
  5628. '###|###',
  5629. TRUE,
  5630. FALSE
  5631. );
  5632. $form = $this->getUpdateDbFormWrap($action_type, $content);
  5633. $this->message($tLabel, 'Select tables to import', '
  5634. <p>
  5635. This is an overview of the CREATE TABLE
  5636. definitions in the SQL file.
  5637. <br />
  5638. Select which tables you want to dump to
  5639. the database.
  5640. <br />
  5641. Any table you choose dump to the
  5642. database is dropped from the database
  5643. first, so you\'ll lose all data in
  5644. existing tables.
  5645. </p>
  5646. ' . $form, 1, 1);
  5647. } else {
  5648. $this->message($tLabel, 'No tables', '
  5649. <p>
  5650. There seems to be no CREATE TABLE
  5651. definitions in the SQL file.
  5652. <br />
  5653. This tool is intelligently creating one
  5654. table at a time and not just dumping the
  5655. whole content of the file uncritically.
  5656. That\'s why there must be defined tables
  5657. in the SQL file.
  5658. </p>
  5659. ', 3, 1);
  5660. }
  5661. }
  5662. }
  5663. break;
  5664. case 'view':
  5665. if (@is_file($actionParts[1])) {
  5666. $tLabel = 'Import SQL dump';
  5667. // Getting statement array from
  5668. $fileContent = t3lib_div::getUrl($actionParts[1]);
  5669. $statements = $this->sqlHandler->getStatementArray($fileContent, 1);
  5670. $maxL = 1000;
  5671. $strLen = strlen($fileContent);
  5672. $maxlen = 200+($maxL-t3lib_utility_Math::forceIntegerInRange(($strLen-20000)/100, 0, $maxL));
  5673. if (count($statements)) {
  5674. $out = '';
  5675. foreach ($statements as $statement) {
  5676. $out.= '<p>' . nl2br(htmlspecialchars(t3lib_div::fixed_lgd_cs($statement, $maxlen))) . '</p>';
  5677. }
  5678. }
  5679. $this->message($tLabel, 'Content of '.basename($actionParts[1]), $out, 1);
  5680. }
  5681. break;
  5682. // Create admin user
  5683. case 'adminUser':
  5684. if ($whichTables['be_users']) {
  5685. if (is_array($this->INSTALL['database_adminUser'])) {
  5686. $username = preg_replace('/[^\da-z._-]/i', '', trim($this->INSTALL['database_adminUser']['username']));
  5687. $pass = trim($this->INSTALL['database_adminUser']['password']);
  5688. $pass2 = trim($this->INSTALL['database_adminUser']['password2']);
  5689. if ($username && $pass && $pass2) {
  5690. if ($pass != $pass2) {
  5691. $this->message($headCode, 'Passwords are not equal!', '
  5692. <p>
  5693. The passwords entered twice are not
  5694. equal.
  5695. </p>
  5696. ', 2, 1);
  5697. } else {
  5698. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'be_users', 'username='.$GLOBALS['TYPO3_DB']->fullQuoteStr($username, 'be_users'));
  5699. if (!$GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
  5700. $insertFields = array(
  5701. 'username' => $username,
  5702. 'password' => md5($pass),
  5703. 'admin' => 1,
  5704. 'uc' => '',
  5705. 'fileoper_perms' => 0,
  5706. 'tstamp' => $GLOBALS['EXEC_TIME'],
  5707. 'crdate' => $GLOBALS['EXEC_TIME']
  5708. );
  5709. $result = $GLOBALS['TYPO3_DB']->exec_INSERTquery('be_users', $insertFields);
  5710. $this->isBasicComplete($headCode);
  5711. if ($result) {
  5712. $this->message($headCode, 'User created', '
  5713. <p>
  5714. Username:
  5715. <strong>' .
  5716. htmlspecialchars($username) . '
  5717. </strong>
  5718. </p>
  5719. ', 1, 1);
  5720. } else {
  5721. $this->message($headCode, 'User not created', '
  5722. <p>
  5723. Error:
  5724. <strong>' .
  5725. htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error()) . '
  5726. </strong>
  5727. </p>
  5728. ', 3, 1);
  5729. }
  5730. } else {
  5731. $this->message($headCode, 'Username not unique!', '
  5732. <p>
  5733. The username,
  5734. <strong>' .
  5735. htmlspecialchars($username) . '
  5736. </strong>
  5737. , was not unique.
  5738. </p>
  5739. ', 2, 1);
  5740. }
  5741. }
  5742. } else {
  5743. $this->message($headCode, 'Missing data!', '
  5744. <p>
  5745. Not all required form fields have been
  5746. filled.
  5747. </p>
  5748. ', 2, 1);
  5749. }
  5750. }
  5751. // Get the template file
  5752. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckTheDatabaseAdminUser.html');
  5753. // Get the template part from the file
  5754. $content = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  5755. // Define the markers content
  5756. $contentMarkers = array(
  5757. 'userName' => 'username - unique, no space, lowercase',
  5758. 'password' => 'password',
  5759. 'repeatPassword' => 'password (repeated)'
  5760. );
  5761. // Fill the markers
  5762. $content = t3lib_parsehtml::substituteMarkerArray(
  5763. $content,
  5764. $contentMarkers,
  5765. '###|###',
  5766. TRUE,
  5767. FALSE
  5768. );
  5769. $form = $this->getUpdateDbFormWrap($action_type, $content);
  5770. $this->message($headCode, 'Create admin user', '
  5771. <p>
  5772. Enter username and password for a new admin
  5773. user.
  5774. <br />
  5775. You should use this function only if there are
  5776. no admin users in the database, for instance if
  5777. this is a blank database.
  5778. <br />
  5779. After you\'ve created the user, log in and add
  5780. the rest of the user information, like email and
  5781. real name.
  5782. </p>
  5783. ' . $form, 0, 1);
  5784. } else {
  5785. $this->message($headCode, 'Required table not in database', '
  5786. <p>
  5787. \'be_users\' must be a table in the database!
  5788. </p>
  5789. ', 3, 1);
  5790. }
  5791. break;
  5792. // clear uc
  5793. case 'UC':
  5794. if ($whichTables['be_users']) {
  5795. if (!strcmp($this->INSTALL['database_UC'], 1)) {
  5796. $GLOBALS['TYPO3_DB']->exec_UPDATEquery('be_users', '', array('uc' => ''));
  5797. $this->message($headCode, 'Clearing be_users.uc', '
  5798. <p>
  5799. Done.
  5800. </p>
  5801. ', 1);
  5802. }
  5803. // Get the template file
  5804. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckTheDatabaseUc.html');
  5805. // Get the template part from the file
  5806. $content = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  5807. // Define the markers content
  5808. $contentMarkers = array(
  5809. 'clearBeUsers' => 'Clear be_users preferences ("uc" field)'
  5810. );
  5811. // Fill the markers
  5812. $content = t3lib_parsehtml::substituteMarkerArray(
  5813. $content,
  5814. $contentMarkers,
  5815. '###|###',
  5816. TRUE,
  5817. FALSE
  5818. );
  5819. $form = $this->getUpdateDbFormWrap($action_type, $content);
  5820. $this->message($headCode, 'Clear user preferences', '
  5821. <p>
  5822. If you press this button all backend users from
  5823. the tables be_users will have their user
  5824. preferences cleared (field \'uc\' set to an
  5825. empty string).
  5826. <br />
  5827. This may come in handy in rare cases where that
  5828. configuration may be corrupt.
  5829. <br />
  5830. Clearing this will clear all user settings from
  5831. the \'Setup\' module.
  5832. </p>
  5833. ' . $form);
  5834. } else {
  5835. $this->message($headCode, 'Required table not in database', '
  5836. <p>
  5837. \'be_users\' must be a table in the database!
  5838. </p>
  5839. ', 3);
  5840. }
  5841. break;
  5842. case 'cache':
  5843. $tableListArr = explode(',', 'cache_pages,cache_pagesection,cache_hash,cache_imagesizes,--div--,sys_log,sys_history,--div--,be_sessions,fe_sessions,fe_session_data' .
  5844. (t3lib_extMgm::isLoaded('indexed_search') ? ',--div--,index_words,index_rel,index_phash,index_grlist,index_section,index_fulltext' : '').
  5845. (t3lib_extMgm::isLoaded('tt_products') ? ',--div--,sys_products_orders,sys_products_orders_mm_tt_products' : '').
  5846. (t3lib_extMgm::isLoaded('direct_mail') ? ',--div--,sys_dmail_maillog' : '').
  5847. (t3lib_extMgm::isLoaded('sys_stat') ? ',--div--,sys_stat' : '')
  5848. );
  5849. if (is_array($this->INSTALL['database_clearcache'])) {
  5850. $qList = array();
  5851. // Get the template file
  5852. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckTheDatabaseCache.html');
  5853. // Get the subpart for emptied tables
  5854. $emptiedTablesSubpart = t3lib_parsehtml::getSubpart($templateFile, '###EMPTIEDTABLES###');
  5855. // Get the subpart for table
  5856. $tableSubpart = t3lib_parsehtml::getSubpart($emptiedTablesSubpart, '###TABLE###');
  5857. foreach ($tableListArr as $table) {
  5858. if ($table!='--div--') {
  5859. $table_c = TYPO3_OS=='WIN' ? strtolower($table) : $table;
  5860. if ($this->INSTALL['database_clearcache'][$table] && $whichTables[$table_c]) {
  5861. $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery($table);
  5862. // Define the markers content
  5863. $emptiedTablesMarkers = array(
  5864. 'tableName' => $table
  5865. );
  5866. // Fill the markers in the subpart
  5867. $qList[] = t3lib_parsehtml::substituteMarkerArray(
  5868. $tableSubpart,
  5869. $emptiedTablesMarkers,
  5870. '###|###',
  5871. TRUE,
  5872. FALSE
  5873. );
  5874. }
  5875. }
  5876. }
  5877. // Substitute the subpart for table
  5878. $emptiedTablesSubpart = t3lib_parsehtml::substituteSubpart(
  5879. $emptiedTablesSubpart,
  5880. '###TABLE###',
  5881. implode(LF, $qList)
  5882. );
  5883. if (count($qList)) {
  5884. $this->message($headCode, 'Clearing cache', '
  5885. <p>
  5886. The following tables were emptied:
  5887. </p>
  5888. ' . $emptiedTablesSubpart, 1);
  5889. }
  5890. }
  5891. // Count entries and make checkboxes
  5892. $labelArr = array(
  5893. 'cache_pages' => 'Pages',
  5894. 'cache_pagesection' => 'TS template related information',
  5895. 'cache_hash' => 'Multipurpose md5-hash cache',
  5896. 'cache_imagesizes' => 'Cached image sizes',
  5897. 'sys_log' => 'Backend action logging',
  5898. 'sys_stat' => 'Page hit statistics',
  5899. 'sys_history' => 'Addendum to the sys_log which tracks ALL changes to content through TCE. May become huge by time. Is used for rollback (undo) and the WorkFlow engine.',
  5900. 'be_sessions' => 'Backend User sessions',
  5901. 'fe_sessions' => 'Frontend User sessions',
  5902. 'fe_session_data' => 'Frontend User sessions data',
  5903. 'sys_dmail_maillog' => 'Direct Mail log',
  5904. 'sys_products_orders' => 'tt_product orders',
  5905. 'sys_products_orders_mm_tt_products' => 'relations between tt_products and sys_products_orders'
  5906. );
  5907. $countEntries=array();
  5908. reset($tableListArr);
  5909. // Get the template file
  5910. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'CheckTheDatabaseCache.html');
  5911. // Get the subpart for table list
  5912. $tableListSubpart = t3lib_parsehtml::getSubpart($templateFile, '###TABLELIST###');
  5913. // Get the subpart for the group separator
  5914. $groupSubpart = t3lib_parsehtml::getSubpart($tableListSubpart, '###GROUP###');
  5915. // Get the subpart for a single table
  5916. $singleTableSubpart = t3lib_parsehtml::getSubpart($tableListSubpart, '###SINGLETABLE###');
  5917. $checkBoxes = array();
  5918. foreach ($tableListArr as $table) {
  5919. if ($table!='--div--') {
  5920. $table_c = TYPO3_OS=='WIN' ? strtolower($table) : $table;
  5921. if ($whichTables[$table_c]) {
  5922. $countEntries[$table] = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', $table);
  5923. // Checkboxes:
  5924. if (
  5925. $this->INSTALL['database_clearcache'][$table] ||
  5926. $_GET['PRESET']['database_clearcache'][$table]
  5927. ) {
  5928. $checked = 'checked="checked"';
  5929. } else {
  5930. $checked = '';
  5931. }
  5932. // Define the markers content
  5933. $singleTableMarkers = array(
  5934. 'table' => $table,
  5935. 'checked' => $checked,
  5936. 'count' => '(' . $countEntries[$table] . ' rows)',
  5937. 'label' => $labelArr[$table]
  5938. );
  5939. // Fill the markers in the subpart
  5940. $checkBoxes[] = t3lib_parsehtml::substituteMarkerArray(
  5941. $singleTableSubpart,
  5942. $singleTableMarkers,
  5943. '###|###',
  5944. TRUE,
  5945. FALSE
  5946. );
  5947. }
  5948. } else {
  5949. $checkBoxes[] = $groupSubpart;
  5950. }
  5951. }
  5952. // Substitute the subpart for the single tables
  5953. $content = t3lib_parsehtml::substituteSubpart(
  5954. $tableListSubpart,
  5955. '###SINGLETABLE###',
  5956. implode(LF, $checkBoxes)
  5957. );
  5958. // Substitute the subpart for the group separator
  5959. $content = t3lib_parsehtml::substituteSubpart(
  5960. $content,
  5961. '###GROUP###',
  5962. ''
  5963. );
  5964. $form = $this->getUpdateDbFormWrap($action_type, $content);
  5965. $this->message($headCode, 'Clear out selected tables', '
  5966. <p>
  5967. Pressing this button will delete all records from
  5968. the selected tables.
  5969. </p>
  5970. ' . $form);
  5971. break;
  5972. }
  5973. }
  5974. $this->output($this->outputWrapper($this->printAll()));
  5975. }
  5976. /**
  5977. * Generates update wizard
  5978. *
  5979. * @return void
  5980. */
  5981. function updateWizard() {
  5982. // clear cache files
  5983. t3lib_extMgm::removeCacheFiles(t3lib_extMgm::getCacheFilePrefix());
  5984. // Forces creation / update of caching framework tables that are needed by some update wizards
  5985. $cacheTablesConfiguration = implode(LF, $this->sqlHandler->getStatementArray(t3lib_cache::getDatabaseTableDefinitions(), 1, '^CREATE TABLE '));
  5986. $neededTableDefinition = $this->sqlHandler->getFieldDefinitions_fileContent($cacheTablesConfiguration);
  5987. $currentTableDefinition = $this->sqlHandler->getFieldDefinitions_database();
  5988. $updateTableDefenition = $this->sqlHandler->getDatabaseExtra($neededTableDefinition, $currentTableDefinition);
  5989. $updateStatements = $this->sqlHandler->getUpdateSuggestions($updateTableDefenition);
  5990. if (isset($updateStatements['create_table']) && count($updateStatements['create_table']) > 0) {
  5991. $this->sqlHandler->performUpdateQueries($updateStatements['create_table'], $updateStatements['create_table']);
  5992. }
  5993. if (isset($updateStatements['add']) && count($updateStatements['add']) > 0) {
  5994. $this->sqlHandler->performUpdateQueries($updateStatements['add'], $updateStatements['add']);
  5995. }
  5996. if (isset($updateStatements['change']) && count($updateStatements['change']) > 0) {
  5997. $this->sqlHandler->performUpdateQueries($updateStatements['change'], $updateStatements['change']);
  5998. }
  5999. // call wizard
  6000. $action = ($this->INSTALL['database_type'] ? $this->INSTALL['database_type'] : 'checkForUpdate');
  6001. $this->updateWizard_parts($action);
  6002. $this->output($this->outputWrapper($this->printAll()));
  6003. }
  6004. /**
  6005. * Implements the steps for the update wizard
  6006. *
  6007. * @param string $action Which should be done.
  6008. * @return void
  6009. */
  6010. function updateWizard_parts($action) {
  6011. $content = '';
  6012. $updateItems = array();
  6013. // Get the template file
  6014. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'UpdateWizardParts.html');
  6015. switch ($action) {
  6016. // first step - check for updates available
  6017. case 'checkForUpdate':
  6018. // Get the subpart for check for update
  6019. $checkForUpdateSubpart = t3lib_parsehtml::getSubpart($templateFile, '###CHECKFORUPDATE###');
  6020. $title = 'Step 1 - Introduction';
  6021. $updateWizardBoxes = '';
  6022. if (!$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']) {
  6023. $updatesAvailableSubpart = '
  6024. <p>
  6025. <strong>
  6026. No updates registered!
  6027. </strong>
  6028. </p>
  6029. ';
  6030. } else {
  6031. // step through list of updates, and check if update is needed and if yes, output an explanation
  6032. $updatesAvailableSubpart = t3lib_parsehtml::getSubpart($checkForUpdateSubpart, '###UPDATESAVAILABLE###');
  6033. $updateWizardBoxesSubpart = t3lib_parsehtml::getSubpart($updatesAvailableSubpart, '###UPDATEWIZARDBOXES###');
  6034. $singleUpdateWizardBoxSubpart = t3lib_parsehtml::getSubpart($updateWizardBoxesSubpart, '###SINGLEUPDATEWIZARDBOX###');
  6035. $singleUpdate = array();
  6036. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'] as $identifier => $className) {
  6037. $tmpObj = $this->getUpgradeObjInstance($className, $identifier);
  6038. if ($tmpObj->shouldRenderWizard()) {
  6039. $explanation = '';
  6040. $tmpObj->checkForUpdate($explanation);
  6041. $updateMarkers = array(
  6042. 'next' => '<button type="submit" name="TYPO3_INSTALL[update][###IDENTIFIER###]">
  6043. Next
  6044. <span class="t3-install-form-button-icon-positive">&nbsp;</span>
  6045. </button>',
  6046. 'identifier' => $identifier,
  6047. 'title' => $tmpObj->getTitle(),
  6048. 'explanation' => $explanation,
  6049. );
  6050. // only display the message, no button
  6051. if (!$tmpObj->shouldRenderNextButton()) {
  6052. $updateMarkers['next'] = '';
  6053. }
  6054. $singleUpdate[] = t3lib_parsehtml::substituteMarkerArray(
  6055. $singleUpdateWizardBoxSubpart,
  6056. $updateMarkers,
  6057. '###|###',
  6058. TRUE,
  6059. FALSE
  6060. );
  6061. }
  6062. }
  6063. if (!empty($singleUpdate)) {
  6064. $updateWizardBoxesSubpart = t3lib_parsehtml::substituteSubpart(
  6065. $updateWizardBoxesSubpart,
  6066. '###SINGLEUPDATEWIZARDBOX###',
  6067. implode(LF, $singleUpdate)
  6068. );
  6069. $updateWizardBoxesMarkers = array(
  6070. 'action' => $this->action
  6071. );
  6072. $updateWizardBoxesSubpart = t3lib_parsehtml::substituteMarkerArray(
  6073. $updateWizardBoxesSubpart,
  6074. $updateWizardBoxesMarkers,
  6075. '###|###',
  6076. TRUE,
  6077. FALSE
  6078. );
  6079. } else {
  6080. $updateWizardBoxesSubpart = '
  6081. <p>
  6082. <strong>
  6083. No updates to perform!
  6084. </strong>
  6085. </p>
  6086. ';
  6087. }
  6088. $updatesAvailableSubpart = t3lib_parsehtml::substituteSubpart(
  6089. $updatesAvailableSubpart,
  6090. '###UPDATEWIZARDBOXES###',
  6091. $updateWizardBoxesSubpart
  6092. );
  6093. $updatesAvailableMarkers = array(
  6094. 'finalStep' => 'Final Step',
  6095. 'finalStepExplanation' => '
  6096. <p>
  6097. When all updates are done you should check
  6098. your database for required updates.
  6099. <br />
  6100. Perform
  6101. <strong>
  6102. COMPARE DATABASE
  6103. </strong>
  6104. as often until no more changes are required.
  6105. <br />
  6106. <br />
  6107. </p>
  6108. ',
  6109. 'compareDatabase' => 'COMPARE DATABASE'
  6110. );
  6111. $updatesAvailableSubpart = t3lib_parsehtml::substituteMarkerArray(
  6112. $updatesAvailableSubpart,
  6113. $updatesAvailableMarkers,
  6114. '###|###',
  6115. TRUE,
  6116. FALSE
  6117. );
  6118. }
  6119. $content = t3lib_parsehtml::substituteSubpart(
  6120. $checkForUpdateSubpart,
  6121. '###UPDATESAVAILABLE###',
  6122. $updatesAvailableSubpart
  6123. );
  6124. break;
  6125. // second step - get user input and ask for final confirmation
  6126. case 'getUserInput':
  6127. $title = 'Step 2 - Configuration of updates';
  6128. $getUserInputSubpart = t3lib_parsehtml::getSubpart($templateFile, '###GETUSERINPUT###');
  6129. $markers = array(
  6130. 'introduction' => 'The following updates will be performed:',
  6131. 'showDatabaseQueries' => 'Show database queries performed',
  6132. 'performUpdates' => 'Perform updates!',
  6133. 'action' => $this->action
  6134. );
  6135. if (!$this->INSTALL['update']) {
  6136. $noUpdatesAvailableSubpart = t3lib_parsehtml::getSubpart($getUserInputSubpart, '###NOUPDATESAVAILABLE###');
  6137. $noUpdateMarkers['noUpdates'] = 'No updates selected!';
  6138. $noUpdatesAvailableSubpart = t3lib_parsehtml::substituteMarkerArray(
  6139. $noUpdatesAvailableSubpart,
  6140. $noUpdateMarkers,
  6141. '###|###',
  6142. TRUE,
  6143. FALSE
  6144. );
  6145. break;
  6146. } else {
  6147. // update methods might need to get custom data
  6148. $updatesAvailableSubpart = t3lib_parsehtml::getSubpart($getUserInputSubpart, '###UPDATESAVAILABLE###');
  6149. $updateItems = array();
  6150. foreach ($this->INSTALL['update'] as $identifier => $tmp) {
  6151. $updateMarkers = array();
  6152. $className = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$identifier];
  6153. $tmpObj = $this->getUpgradeObjInstance($className, $identifier);
  6154. $updateMarkers['identifier'] = $identifier;
  6155. $updateMarkers['title'] = $tmpObj->getTitle();
  6156. if (method_exists($tmpObj, 'getUserInput')) {
  6157. $updateMarkers['identifierMethod'] = $tmpObj->getUserInput('TYPO3_INSTALL[update][' . $identifier . ']');
  6158. }
  6159. $updateItems[] = t3lib_parsehtml::substituteMarkerArray(
  6160. $updatesAvailableSubpart,
  6161. $updateMarkers,
  6162. '###|###',
  6163. TRUE,
  6164. TRUE
  6165. );
  6166. }
  6167. $updatesAvailableSubpart = implode(LF, $updateItems);
  6168. }
  6169. $content = t3lib_parsehtml::substituteSubpart(
  6170. $getUserInputSubpart,
  6171. '###NOUPDATESAVAILABLE###',
  6172. $noUpdatesAvailableSubpart
  6173. );
  6174. $content = t3lib_parsehtml::substituteSubpart(
  6175. $content,
  6176. '###UPDATESAVAILABLE###',
  6177. $updatesAvailableSubpart
  6178. );
  6179. $content = t3lib_parsehtml::substituteMarkerArray(
  6180. $content,
  6181. $markers,
  6182. '###|###',
  6183. TRUE,
  6184. FALSE
  6185. );
  6186. break;
  6187. case 'performUpdate': // third step - perform update
  6188. $title = 'Step 3 - Perform updates';
  6189. $performUpdateSubpart = t3lib_parsehtml::getSubpart($templateFile, '###PERFORMUPDATE###');
  6190. $updateItemsSubpart = t3lib_parsehtml::getSubpart($performUpdateSubpart, '###UPDATEITEMS###');
  6191. $checkUserInputSubpart = t3lib_parsehtml::getSubpart($updateItemsSubpart, '###CHECKUSERINPUT###');
  6192. $updatePerformedSubpart = t3lib_parsehtml::getSubpart($updateItemsSubpart, '###UPDATEPERFORMED###');
  6193. $noPerformUpdateSubpart = t3lib_parsehtml::getSubpart($updateItemsSubpart, '###NOPERFORMUPDATE###');
  6194. $databaseQueriesSubpart = t3lib_parsehtml::getSubpart($updatePerformedSubpart, '###DATABASEQUERIES###');
  6195. $customOutputSubpart = t3lib_parsehtml::getSubpart($updatePerformedSubpart, '###CUSTOMOUTPUT###');
  6196. if (!$this->INSTALL['update']['extList']) { break; }
  6197. $GLOBALS['TYPO3_DB']->store_lastBuiltQuery = TRUE;
  6198. foreach ($this->INSTALL['update']['extList'] as $identifier) {
  6199. $className = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$identifier];
  6200. $tmpObj = $this->getUpgradeObjInstance($className, $identifier);
  6201. $updateItemsMarkers['identifier'] = $identifier;
  6202. $updateItemsMarkers['title'] = $tmpObj->getTitle();
  6203. // check user input if testing method is available
  6204. if (method_exists($tmpObj, 'checkUserInput') && !$tmpObj->checkUserInput($customOutput)) {
  6205. $customOutput = '';
  6206. $userInputMarkers = array(
  6207. 'customOutput' => ($customOutput ? $customOutput : 'Something went wrong'),
  6208. 'goBack' => 'Go back to update configuration'
  6209. );
  6210. $checkUserInput = t3lib_parsehtml::substituteMarkerArray(
  6211. $checkUserInputSubpart,
  6212. $userInputMarkers,
  6213. '###|###',
  6214. TRUE,
  6215. FALSE
  6216. );
  6217. } else {
  6218. if (method_exists($tmpObj, 'performUpdate')) {
  6219. $customOutput = '';
  6220. $dbQueries = array();
  6221. $databaseQueries = array();
  6222. if ($tmpObj->performUpdate($dbQueries, $customOutput)) {
  6223. $performUpdateMarkers['updateStatus'] = 'Update successful!';
  6224. } else {
  6225. $performUpdateMarkers['updateStatus'] = 'Update FAILED!';
  6226. }
  6227. if ($this->INSTALL['update']['showDatabaseQueries']) {
  6228. $content .= '<br />' . implode('<br />', $dbQueries);
  6229. foreach($dbQueries as $query) {
  6230. $databaseQueryMarkers['query'] = $query;
  6231. $databaseQueries[] = t3lib_parsehtml::substituteMarkerArray(
  6232. $databaseQueriesSubpart,
  6233. $databaseQueryMarkers,
  6234. '###|###',
  6235. TRUE,
  6236. FALSE
  6237. );
  6238. }
  6239. }
  6240. if (strlen($customOutput)) {
  6241. $content.= '<br />' . $customOutput;
  6242. $customOutputMarkers['custom'] = $customOutput;
  6243. $customOutputItem = t3lib_parsehtml::substituteMarkerArray(
  6244. $customOutputSubpart,
  6245. $customOutputMarkers,
  6246. '###|###',
  6247. TRUE,
  6248. FALSE
  6249. );
  6250. }
  6251. $updatePerformed = t3lib_parsehtml::substituteSubpart(
  6252. $updatePerformedSubpart,
  6253. '###DATABASEQUERIES###',
  6254. implode(LF, $databaseQueries)
  6255. );
  6256. $updatePerformed = t3lib_parsehtml::substituteSubpart(
  6257. $updatePerformed,
  6258. '###CUSTOMOUTPUT###',
  6259. $customOutputItem
  6260. );
  6261. $updatePerformed = t3lib_parsehtml::substituteMarkerArray(
  6262. $updatePerformed,
  6263. $performUpdateMarkers,
  6264. '###|###',
  6265. TRUE,
  6266. FALSE
  6267. );
  6268. } else {
  6269. $noPerformUpdateMarkers['noUpdateMethod'] = 'No update method available!';
  6270. $noPerformUpdate = t3lib_parsehtml::substituteMarkerArray(
  6271. $noPerformUpdateSubpart,
  6272. $noPerformUpdateMarkers,
  6273. '###|###',
  6274. TRUE,
  6275. FALSE
  6276. );
  6277. }
  6278. }
  6279. $updateItem = t3lib_parsehtml::substituteSubpart(
  6280. $updateItemsSubpart,
  6281. '###CHECKUSERINPUT###',
  6282. $checkUserInput
  6283. );
  6284. $updateItem = t3lib_parsehtml::substituteSubpart(
  6285. $updateItem,
  6286. '###UPDATEPERFORMED###',
  6287. $updatePerformed
  6288. );
  6289. $updateItem = t3lib_parsehtml::substituteSubpart(
  6290. $updateItem,
  6291. '###NOPERFORMUPDATE###',
  6292. $noPerformUpdate
  6293. );
  6294. $updateItem = t3lib_parsehtml::substituteSubpart(
  6295. $updateItem,
  6296. '###UPDATEITEMS###',
  6297. implode(LF, $updateItems)
  6298. );
  6299. $updateItems[] = t3lib_parsehtml::substituteMarkerArray(
  6300. $updateItem,
  6301. $updateItemsMarkers,
  6302. '###|###',
  6303. TRUE,
  6304. FALSE
  6305. );
  6306. }
  6307. $content = t3lib_parsehtml::substituteSubpart(
  6308. $performUpdateSubpart,
  6309. '###UPDATEITEMS###',
  6310. implode(LF, $updateItems)
  6311. );
  6312. $GLOBALS['TYPO3_DB']->store_lastBuiltQuery = FALSE;
  6313. // also render the link to the next update wizard, if available
  6314. $nextUpdateWizard = $this->getNextUpdadeWizardInstance($tmpObj);
  6315. if ($nextUpdateWizard) {
  6316. $content = t3lib_parsehtml::substituteMarkerArray(
  6317. $content,
  6318. array('NEXTIDENTIFIER' => $nextUpdateWizard->getIdentifier()),
  6319. '###|###',
  6320. TRUE,
  6321. FALSE
  6322. );
  6323. } else {
  6324. // no next wizard, also hide the button to the next update wizard
  6325. $content = t3lib_parsehtml::substituteSubpart(
  6326. $content,
  6327. '###NEXTUPDATEWIZARD###',
  6328. ''
  6329. );
  6330. }
  6331. break;
  6332. }
  6333. $this->message('Upgrade Wizard', $title, $content);
  6334. }
  6335. /**
  6336. * Creates instance of an upgrade object, setting the pObj, versionNumber and pObj
  6337. *
  6338. * @param string $className The class name
  6339. * @param string $identifier The identifier of upgrade object - needed to fetch user input
  6340. * @return object Newly instanciated upgrade object
  6341. */
  6342. function getUpgradeObjInstance($className, $identifier) {
  6343. $tmpObj = t3lib_div::getUserObj($className);
  6344. $tmpObj->setIdentifier($identifier);
  6345. $tmpObj->versionNumber = t3lib_utility_VersionNumber::convertVersionNumberToInteger(TYPO3_version);
  6346. $tmpObj->pObj = $this;
  6347. $tmpObj->userInput = $this->INSTALL['update'][$identifier];
  6348. return $tmpObj;
  6349. }
  6350. /**
  6351. * Returns the next upgrade wizard object.
  6352. *
  6353. * Used to show the link/button to the next upgrade wizard
  6354. * @param object $currentObj current Upgrade Wizard Object
  6355. * @return mixed Upgrade Wizard instance or FALSE
  6356. */
  6357. protected function getNextUpdadeWizardInstance($currentObj) {
  6358. $isPreviousRecord = TRUE;
  6359. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'] as $identifier => $className) {
  6360. // first, find the current update wizard, and then start validating the next ones
  6361. if ($currentObj->getIdentifier() == $identifier) {
  6362. $isPreviousRecord = FALSE;
  6363. continue;
  6364. }
  6365. if (!$isPreviousRecord) {
  6366. $nextUpdateWizard = $this->getUpgradeObjInstance($className, $identifier);
  6367. if ($nextUpdateWizard->shouldRenderWizard()) {
  6368. return $nextUpdateWizard;
  6369. }
  6370. }
  6371. }
  6372. return FALSE;
  6373. }
  6374. /**
  6375. * Check if at lease one backend admin user has been created
  6376. *
  6377. * @return integer Amount of backend users in the database
  6378. */
  6379. function isBackendAdminUser() {
  6380. return $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'be_users', 'admin=1');
  6381. }
  6382. /**
  6383. * Check if the basic settings are complete
  6384. * Only used by 1-2-3 mode
  6385. *
  6386. * @param string $tLabel The header for the message
  6387. * @return boolean TRUE if complete
  6388. */
  6389. function isBasicComplete($tLabel) {
  6390. if ($this->mode=='123') {
  6391. $tables = $this->sqlHandler->getListOfTables();
  6392. if (count($tables)) {
  6393. $beuser = $this->isBackendAdminUser();
  6394. }
  6395. if (count($tables) && $beuser) {
  6396. $mode123Imported=1;
  6397. $this->message($tLabel, 'Basic Installation Completed', $this->messageBasicFinished(), -1, 1);
  6398. $this->message($tLabel, 'Security Risk!', $this->securityRisk().$this->alterPasswordForm(), 2, 1);
  6399. } else {
  6400. $this->message($tLabel, 'Still missing something?', nl2br('
  6401. You may be missing one of these points before your TYPO3 installation is complete:
  6402. '.(count($tables)?'':'- You haven\'t imported any tables yet.
  6403. ')
  6404. .($beuser?'':'- You haven\'t created an admin user yet.
  6405. ')
  6406. .'
  6407. You\'re about to import a database with a complete site in it, these three points should be met.
  6408. '), -1, 1);
  6409. }
  6410. }
  6411. return $mode123Imported;
  6412. }
  6413. /**
  6414. * Generate the contents for the form for 'Database Analyzer'
  6415. * when the 'COMPARE' still contains errors
  6416. *
  6417. * @param string $type get_form if the form needs to be generated
  6418. * @param array $arr_update The tables/fields which needs an update
  6419. * @param array $arr_remove The tables/fields which needs to be removed
  6420. * @param string $action_type The action type
  6421. * @return string HTML for the form
  6422. */
  6423. function generateUpdateDatabaseForm($type, $arr_update, $arr_remove, $action_type) {
  6424. $content = '';
  6425. switch($type) {
  6426. case 'get_form':
  6427. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['clear_table'], 'Clear tables (use with care!)', FALSE, TRUE);
  6428. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['add'], 'Add fields');
  6429. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['change'], 'Changing fields', (t3lib_extMgm::isLoaded('dbal')?0:1), 0, $arr_update['change_currentValue']);
  6430. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['change'], 'Remove unused fields (rename with prefix)', $this->setAllCheckBoxesByDefault, 1);
  6431. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop'], 'Drop fields (really!)', $this->setAllCheckBoxesByDefault);
  6432. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['create_table'], 'Add tables');
  6433. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['change_table'], 'Removing tables (rename with prefix)', $this->setAllCheckBoxesByDefault, 1, $arr_remove['tables_count'], 1);
  6434. $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop_table'], 'Drop tables (really!)', $this->setAllCheckBoxesByDefault, 0, $arr_remove['tables_count'], 1);
  6435. $content = $this->getUpdateDbFormWrap($action_type, $content);
  6436. break;
  6437. default:
  6438. break;
  6439. }
  6440. return $content;
  6441. }
  6442. /**
  6443. * Form wrap for 'Database Analyzer'
  6444. * when the 'COMPARE' still contains errors
  6445. *
  6446. * @param string $action_type The action type
  6447. * @param string $content The form content
  6448. * @param string $label The submit button label
  6449. * @return string HTML of the form
  6450. */
  6451. function getUpdateDbFormWrap($action_type, $content, $label='Write to database') {
  6452. // Get the template file
  6453. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'GetUpdateDbFormWrap.html');
  6454. // Get the template part from the file
  6455. $form = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  6456. // Define the markers content
  6457. $formMarkers = array(
  6458. 'action' => $this->action,
  6459. 'actionType' => htmlspecialchars($action_type),
  6460. 'content' => $content,
  6461. 'label' => $label
  6462. );
  6463. // Fill the markers
  6464. $form = t3lib_parsehtml::substituteMarkerArray(
  6465. $form,
  6466. $formMarkers,
  6467. '###|###',
  6468. TRUE,
  6469. FALSE
  6470. );
  6471. return $form;
  6472. }
  6473. /**
  6474. * Generates an HTML table for the setup of database tables
  6475. * Used in 'Database analyzer > Compare with $TCA'
  6476. *
  6477. * @param array $arr Description of the table with fieldname and fieldcontent
  6478. * @param boolean $pre TRUE if the field content needs to be wrapped with a <pre> tag
  6479. * @param string $label The header label
  6480. * @return string HTML of the table
  6481. */
  6482. function displayFields($arr, $pre=0, $label='') {
  6483. // Get the template file
  6484. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'DisplayFields.html');
  6485. // Get the template part from the file
  6486. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  6487. // Define the markers content
  6488. $templateMarkers = array(
  6489. 'headerFieldName' => 'Field name:',
  6490. 'headerLabel' => $label ? $label : 'Info:'
  6491. );
  6492. if (is_array($arr)) {
  6493. $rows = array();
  6494. // Get the subpart for rows
  6495. $rowsSubpart = t3lib_parsehtml::getSubpart($template, '###ROWS###');
  6496. foreach ($arr as $fieldname => $fieldContent) {
  6497. if ($pre) {
  6498. $fieldContent = '<pre>'.trim($fieldContent).'</pre>';
  6499. }
  6500. // Define the markers content
  6501. $rowsMarkers = array(
  6502. 'fieldName' => $fieldname,
  6503. 'fieldContent' => $fieldContent
  6504. );
  6505. // Fill the markers in the subpart
  6506. $rows[] = t3lib_parsehtml::substituteMarkerArray(
  6507. $rowsSubpart,
  6508. $rowsMarkers,
  6509. '###|###',
  6510. TRUE,
  6511. FALSE
  6512. );
  6513. }
  6514. }
  6515. // Substitute the subpart for rows
  6516. $template = t3lib_parsehtml::substituteSubpart(
  6517. $template,
  6518. '###ROWS###',
  6519. implode(LF, $rows)
  6520. );
  6521. // Fill the markers
  6522. $template = t3lib_parsehtml::substituteMarkerArray(
  6523. $template,
  6524. $templateMarkers,
  6525. '###|###',
  6526. TRUE,
  6527. FALSE
  6528. );
  6529. return $template;
  6530. }
  6531. /**
  6532. * Generates an HTML table with comparison between database and $TCA
  6533. * Used in 'Database analyzer > Compare with $TCA'
  6534. *
  6535. * @param array $arr Description of the table with fieldname and fieldcontent
  6536. * @param array $arr_db The actual content of a field in the database
  6537. * @return string HTML of the table
  6538. */
  6539. function displayFieldComp($arr, $arr_db) {
  6540. // Get the template file
  6541. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'DisplayFieldComp.html');
  6542. // Get the template part from the file
  6543. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  6544. // Define the markers content
  6545. $templateMarkers = array(
  6546. 'headerFieldName' => 'Field name:',
  6547. 'headerSuggested' => 'Suggested value from $TCA:',
  6548. 'headerActual' => 'Actual value from database:'
  6549. );
  6550. $rows = array();
  6551. if (is_array($arr)) {
  6552. // Get the subpart for rows
  6553. $rowsSubpart = t3lib_parsehtml::getSubpart($template, '###ROWS###');
  6554. foreach ($arr as $fieldname => $fieldContent) {
  6555. // This tries to equalize the types tinyint and int
  6556. $str1 = $fieldContent;
  6557. $str2 = trim($arr_db[$fieldname]);
  6558. $str1 = str_replace('tinyint(3)', 'tinyint(4)', $str1);
  6559. $str2 = str_replace('tinyint(3)', 'tinyint(4)', $str2);
  6560. $str1 = str_replace('int(10)', 'int(11)', $str1);
  6561. $str2 = str_replace('int(10)', 'int(11)', $str2);
  6562. // Compare:
  6563. if (strcmp($str1, $str2)) {
  6564. $bgcolor=' class="warning"';
  6565. } else {
  6566. $bgcolor='';
  6567. }
  6568. // Define the markers content
  6569. $rowsMarkers = array(
  6570. 'fieldName' => $fieldname,
  6571. 'fieldContent' => $fieldContent,
  6572. 'fieldContentDb' => $arr_db[$fieldname],
  6573. 'class' => $bgcolor
  6574. );
  6575. // Fill the markers in the subpart
  6576. $rows[] = t3lib_parsehtml::substituteMarkerArray(
  6577. $rowsSubpart,
  6578. $rowsMarkers,
  6579. '###|###',
  6580. TRUE,
  6581. FALSE
  6582. );
  6583. }
  6584. }
  6585. // Substitute the subpart for rows
  6586. $template = t3lib_parsehtml::substituteSubpart(
  6587. $template,
  6588. '###ROWS###',
  6589. implode(LF, $rows)
  6590. );
  6591. // Fill the markers
  6592. $out = t3lib_parsehtml::substituteMarkerArray(
  6593. $template,
  6594. $templateMarkers,
  6595. '###|###',
  6596. TRUE,
  6597. FALSE
  6598. );
  6599. return $out;
  6600. }
  6601. /**
  6602. * Generates an HTML table with $TCA suggestions looking at the type of field
  6603. * Used in 'Database analyzer > Compare with $TCA'
  6604. *
  6605. * @param array $arr Description of the table with fieldname and fieldcontent
  6606. * @param string $excludeList Comma separated list of fields which should be excluded from this table
  6607. * @return string HTML of the table
  6608. */
  6609. function displaySuggestions($arr, $excludeList='') {
  6610. // Get the template file
  6611. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'DisplaySuggestions.html');
  6612. // Get the template part from the file
  6613. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  6614. $templateMarkers = array();
  6615. $fC=0;
  6616. $rows = array();
  6617. if (is_array($arr)) {
  6618. // Get the subpart for rows
  6619. $rowsSubpart = t3lib_parsehtml::getSubpart($template, '###ROWS###');
  6620. foreach ($arr as $fieldname => $fieldContent) {
  6621. if (!t3lib_div::inList($excludeList, $fieldname) && substr($fieldname, 0, strlen($this->sqlHandler->getDeletedPrefixKey())) != $this->sqlHandler->getDeletedPrefixKey() && substr($fieldname, -1) != '.') {
  6622. if ($arr[$fieldname.'.']) {
  6623. // Get the subpart for pre
  6624. $preSubpart = t3lib_parsehtml::getSubpart($rowsSubpart, '###PRE###');
  6625. // Define the markers content
  6626. $preMarkers = array(
  6627. 'code' => '<pre>' . trim($arr[$fieldname.'.']) . '</pre>'
  6628. );
  6629. // Fill the markers in the subpart
  6630. $preSubpart = t3lib_parsehtml::substituteMarkerArray(
  6631. $preSubpart,
  6632. $preMarkers,
  6633. '###|###',
  6634. TRUE,
  6635. FALSE
  6636. );
  6637. }
  6638. // Substitute the subpart for pre
  6639. $row = t3lib_parsehtml::substituteSubpart(
  6640. $rowsSubpart,
  6641. '###PRE###',
  6642. $preSubpart
  6643. );
  6644. // Define the markers content
  6645. $rowsMarkers = array(
  6646. 'headerFieldName' => 'Field name:',
  6647. 'headerLabel' => 'Info:',
  6648. 'headerSuggestion' => 'Suggestion for the field:',
  6649. 'fieldName' => $fieldname,
  6650. 'fieldContent' => $fieldContent,
  6651. );
  6652. // Fill the markers in the subpart
  6653. $rows[] = t3lib_parsehtml::substituteMarkerArray(
  6654. $row,
  6655. $rowsMarkers,
  6656. '###|###',
  6657. TRUE,
  6658. FALSE
  6659. );
  6660. $fC++;
  6661. }
  6662. }
  6663. }
  6664. // Substitute the subpart for rows
  6665. $template = t3lib_parsehtml::substituteSubpart(
  6666. $template,
  6667. '###ROWS###',
  6668. implode(LF, $rows)
  6669. );
  6670. // Fill the markers
  6671. $out = t3lib_parsehtml::substituteMarkerArray(
  6672. $template,
  6673. $templateMarkers,
  6674. '###|###',
  6675. TRUE,
  6676. FALSE
  6677. );
  6678. return array($out, $fC);
  6679. }
  6680. /**
  6681. * Compares an array with field definitions with $TCA array
  6682. *
  6683. * @param array $FDsrc Field definition source
  6684. * @param array $TCA The TCA array
  6685. * @param boolean $onlyFields
  6686. * @return array
  6687. */
  6688. function compareDatabaseAndTCA($FDsrc, $TCA, $onlyFields=0) {
  6689. $extraArr=array();
  6690. if (is_array($FDsrc)) {
  6691. foreach ($FDsrc as $table => $info) {
  6692. if (!isset($TCA[$table])) {
  6693. if (!$onlyFields) {
  6694. // If the table was not in the FDcomp-array, the result array is loaded with that table.
  6695. $extraArr[$table]=$info;
  6696. $extraArr[$table]['whole_table']=1;
  6697. unset($extraArr[$table]['keys']);
  6698. }
  6699. } else {
  6700. $theKey='fields';
  6701. $excludeListArr=array();
  6702. if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
  6703. $excludeListArr[]=$TCA[$table]['ctrl']['enablecolumns'];
  6704. }
  6705. $excludeListArr[]=$TCA[$table]['ctrl']['tstamp'];
  6706. $excludeListArr[]=$TCA[$table]['ctrl']['sortby'];
  6707. $excludeListArr[]=$TCA[$table]['ctrl']['delete'];
  6708. $excludeListArr[]=$TCA[$table]['ctrl']['cruser_id'];
  6709. $excludeListArr[]=$TCA[$table]['ctrl']['crdate'];
  6710. $excludeListArr[]='uid';
  6711. $excludeListArr[]='pid';
  6712. if ($table=='pages') {
  6713. $excludeListArr[]='perms_userid';
  6714. $excludeListArr[]='perms_groupid';
  6715. $excludeListArr[]='perms_user';
  6716. $excludeListArr[]='perms_group';
  6717. $excludeListArr[]='perms_everybody';
  6718. }
  6719. if ($table=='sys_dmail') {
  6720. $excludeListArr[]='scheduled';
  6721. $excludeListArr[]='scheduled_begin';
  6722. $excludeListArr[]='scheduled_end';
  6723. $excludeListArr[]='query_info';
  6724. }
  6725. if (is_array($info[$theKey])) {
  6726. foreach ($info[$theKey] as $fieldN => $fieldC) {
  6727. if (!isset($TCA[$table]['columns'][$fieldN]) && !in_array($fieldN, $excludeListArr)) {
  6728. $extraArr[$table][$theKey][$fieldN] = $info['fields'][$fieldN];
  6729. $extraArr[$table][$theKey][$fieldN.'.']=$this->suggestTCAFieldDefinition($fieldN, $fieldC);
  6730. }
  6731. }
  6732. }
  6733. }
  6734. }
  6735. }
  6736. return array('extra'=>$extraArr);
  6737. }
  6738. /**
  6739. * Compares the $TCA array with a field definition array
  6740. *
  6741. * @param array $TCA The TCA
  6742. * @param array $FDcomp Field definition comparison
  6743. * @return array
  6744. */
  6745. function compareTCAandDatabase($TCA, $FDcomp) {
  6746. $matchingArr = $extraArr = array();
  6747. if (is_array($TCA)) {
  6748. foreach ($TCA as $table => $info) {
  6749. if (!isset($FDcomp[$table])) {
  6750. // If the table was not in the FDcomp-array, the result array is loaded with that table.
  6751. $extraArr[$table]['whole_table']=1;
  6752. } else {
  6753. foreach ($info['columns'] as $fieldN => $fieldC) {
  6754. $fieldDef = $this->suggestFieldDefinition($fieldC);
  6755. if (!is_array($fieldDef)) {
  6756. if (!isset($FDcomp[$table]['fields'][$fieldN])) {
  6757. $extraArr[$table]['fields'][$fieldN]=$fieldDef;
  6758. } else {
  6759. $matchingArr[$table]['fields'][$fieldN]=$fieldDef;
  6760. }
  6761. }
  6762. }
  6763. }
  6764. }
  6765. }
  6766. return array('extra'=>$extraArr, 'matching'=>$matchingArr);
  6767. }
  6768. /**
  6769. * Suggests a field definition for a TCA config array.
  6770. *
  6771. * @param array $fieldInfo Info of a field
  6772. * @return string The suggestion
  6773. */
  6774. function suggestFieldDefinition($fieldInfo) {
  6775. $out='';
  6776. switch($fieldInfo['config']['type']) {
  6777. case 'input':
  6778. if (preg_match('/date|time|int|year/', $fieldInfo['config']['eval'])) {
  6779. $out = "int(11) NOT NULL default '0'";
  6780. } else {
  6781. $max = intval($fieldInfo['config']['max']);
  6782. if ($max>0 && $max<200) {
  6783. $out = 'varchar('.$max.") NOT NULL default ''";
  6784. } else {
  6785. $out = 'tinytext';
  6786. }
  6787. }
  6788. break;
  6789. case 'text':
  6790. $out = 'text';
  6791. break;
  6792. case 'check':
  6793. if (is_array($fieldInfo['config']['items']) && count($fieldInfo['config']['items'])>8) {
  6794. $out = "int(11) NOT NULL default '0'";
  6795. } else {
  6796. $out = "tinyint(3) NOT NULL default '0'";
  6797. }
  6798. break;
  6799. case 'radio':
  6800. if (is_array($fieldInfo['config']['items'])) {
  6801. $out = $this->getItemArrayType($fieldInfo['config']['items']);
  6802. } else {
  6803. $out = 'ERROR: Radiobox did not have items!';
  6804. }
  6805. break;
  6806. case 'group':
  6807. if ($fieldInfo['config']['internal_type']=='db') {
  6808. $max = t3lib_utility_Math::forceIntegerInRange($fieldInfo['config']['maxitems'], 1, 10000);
  6809. if (count(explode(',', $fieldInfo['config']['allowed']))>1) {
  6810. // Tablenames are 10, "_" 1, uid's 5, comma 1
  6811. $len = $max*(10+1+5+1);
  6812. $out=$this->getItemBlobSize($len);
  6813. } elseif ($max<=1) {
  6814. $out = "int(11) NOT NULL default '0'";
  6815. } else {
  6816. // uid's 5, comma 1
  6817. $len = $max*(5+1);
  6818. $out=$this->getItemBlobSize($len);
  6819. }
  6820. }
  6821. if ($fieldInfo['config']['internal_type']=='file') {
  6822. $max = t3lib_utility_Math::forceIntegerInRange($fieldInfo['config']['maxitems'], 1, 10000);
  6823. // Filenames is 30+ chars....
  6824. $len = $max*(30+1);
  6825. $out=$this->getItemBlobSize($len);
  6826. }
  6827. break;
  6828. case 'select':
  6829. $max = t3lib_utility_Math::forceIntegerInRange($fieldInfo['config']['maxitems'], 1, 10000);
  6830. if ($max<=1) {
  6831. if ($fieldInfo['config']['foreign_table']) {
  6832. $out = "int(11) NOT NULL default '0'";
  6833. } else {
  6834. $out = $this->getItemArrayType($fieldInfo['config']['items']);
  6835. }
  6836. } else {
  6837. // five chars (special=10) + comma:
  6838. $len = $max*(($fieldInfo['config']['special']?10:5)+1);
  6839. $out=$this->getItemBlobSize($len);
  6840. }
  6841. break;
  6842. default:
  6843. break;
  6844. }
  6845. return $out?$out:$fieldInfo;
  6846. }
  6847. /**
  6848. * Check if field needs to be varchar or int
  6849. * Private
  6850. *
  6851. * @param array $arr
  6852. * @return string The definition
  6853. */
  6854. function getItemArrayType($arr) {
  6855. if (is_array($arr)) {
  6856. $type[] = $intSize[] = 0;
  6857. foreach ($arr as $item) {
  6858. if (!t3lib_utility_Math::canBeInterpretedAsInteger($item[1]) && $item[1]!='--div--') {
  6859. $type[]=strlen($item[1]);
  6860. } else {
  6861. $intSize[]=$item[1];
  6862. }
  6863. }
  6864. $us = min($intSize)>=0 ? ' unsigned' : '';
  6865. if (max($type)>0) {
  6866. $out = 'varchar('.max($type).") NOT NULL default ''";
  6867. } else {
  6868. $out = "int(11) NOT NULL default '0'";
  6869. }
  6870. }
  6871. return $out;
  6872. }
  6873. /**
  6874. * Defines the blob size of an item by a given length
  6875. * Private
  6876. *
  6877. * @param integer $len The length
  6878. * @return string The blob definition
  6879. */
  6880. function getItemBlobSize($len) {
  6881. return ($len>255 ? 'tiny' : '').'blob';
  6882. }
  6883. /**
  6884. * Should suggest a TCA configuration for a specific field.
  6885. *
  6886. * @param string $fieldName The field name
  6887. * @param string $fieldInfo The field information
  6888. * @return string Suggested TCA configuration
  6889. */
  6890. function suggestTCAFieldDefinition($fieldName, $fieldInfo) {
  6891. list($type, $len) = preg_split('/ |\(|\)/', $fieldInfo, 3);
  6892. switch($type) {
  6893. case 'int':
  6894. $out="
  6895. '".$fieldName."' => array (
  6896. 'label' => '".strtoupper($fieldName).":',
  6897. 'exclude' => 0,
  6898. 'config' => array (
  6899. 'type' => 'input',
  6900. 'size' => '8',
  6901. 'max' => '20',
  6902. 'eval' => 'date',
  6903. 'default' => '0',
  6904. 'checkbox' => '0'
  6905. )
  6906. ),
  6907. ----- OR -----
  6908. '".$fieldName."' => array (
  6909. 'label' => '".strtoupper($fieldName).":',
  6910. 'exclude' => 0,
  6911. 'config' => array (
  6912. 'type' => 'select',
  6913. 'items' => array (
  6914. array('[nothing]', 0),
  6915. array('Extra choice! Only negative values here.', -1),
  6916. array('__Divider:__', '--div--')
  6917. ),
  6918. 'foreign_table' => '[some_table_name]'
  6919. )
  6920. ),";
  6921. break;
  6922. case 'varchar':
  6923. if ($len>10) {
  6924. $out="
  6925. '".$fieldName."' => array (
  6926. 'label' => '".strtoupper($fieldName).":',
  6927. 'exclude' => 0,
  6928. 'config' => array (
  6929. 'type' => 'input',
  6930. 'size' => '8',
  6931. 'max' => '".$len."',
  6932. 'eval' => 'trim',
  6933. 'default' => ''
  6934. )
  6935. ),";
  6936. } else {
  6937. $out="
  6938. '".$fieldName."' => array (
  6939. 'label' => '".strtoupper($fieldName).":',
  6940. 'exclude' => 0,
  6941. 'config' => array (
  6942. 'type' => 'select',
  6943. 'items' => array (
  6944. array('Item number 1', 'key1'),
  6945. array('Item number 2', 'key2'),
  6946. array('-----', '--div--'),
  6947. array('Item number 3', 'key3')
  6948. ),
  6949. 'default' => '1'
  6950. )
  6951. ),";
  6952. }
  6953. break;
  6954. case 'tinyint':
  6955. $out="
  6956. '".$fieldName."' => array (
  6957. 'label' => '".strtoupper($fieldName).":',
  6958. 'exclude' => 0,
  6959. 'config' => array (
  6960. 'type' => 'select',
  6961. 'items' => array (
  6962. array('Item number 1', '1'),
  6963. array('Item number 2', '2'),
  6964. array('-----', '--div--'),
  6965. array('Item number 3', '3')
  6966. ),
  6967. 'default' => '1'
  6968. )
  6969. ),
  6970. ----- OR -----
  6971. '".$fieldName."' => array (
  6972. 'label' => '".strtoupper($fieldName).":',
  6973. 'exclude' => 0,
  6974. 'config' => array (
  6975. 'type' => 'check',
  6976. 'default' => '1'
  6977. )
  6978. ),";
  6979. break;
  6980. case 'tinytext':
  6981. $out="
  6982. '".$fieldName."' => array (
  6983. 'label' => '".strtoupper($fieldName).":',
  6984. 'exclude' => 0,
  6985. 'config' => array (
  6986. 'type' => 'input',
  6987. 'size' => '40',
  6988. 'max' => '255',
  6989. 'eval' => '',
  6990. 'default' => ''
  6991. )
  6992. ),";
  6993. break;
  6994. case 'text':
  6995. case 'mediumtext':
  6996. $out="
  6997. '".$fieldName."' => array (
  6998. 'label' => '".strtoupper($fieldName).":',
  6999. 'config' => array (
  7000. 'type' => 'text',
  7001. 'cols' => '48',
  7002. 'rows' => '5'
  7003. )
  7004. ),";
  7005. break;
  7006. default:
  7007. $out="
  7008. '".$fieldName."' => array (
  7009. 'label' => '".strtoupper($fieldName).":',
  7010. 'exclude' => 0,
  7011. 'config' => array (
  7012. 'type' => 'input',
  7013. 'size' => '30',
  7014. 'max' => '',
  7015. 'eval' => '',
  7016. 'default' => ''
  7017. )
  7018. ),";
  7019. break;
  7020. }
  7021. return $out?$out:$fieldInfo;
  7022. }
  7023. /**
  7024. * Includes TCA
  7025. *
  7026. * @return void
  7027. */
  7028. function includeTCA() {
  7029. Typo3_Bootstrap::getInstance()->loadExtensionTables();
  7030. foreach ($GLOBALS['TCA'] as $table => $conf) {
  7031. t3lib_div::loadTCA($table);
  7032. }
  7033. }
  7034. /**********************
  7035. *
  7036. * GENERAL FUNCTIONS
  7037. *
  7038. **********************/
  7039. /**
  7040. * Setting a message in the message-log and sets the fatalError flag if error type is 3.
  7041. *
  7042. * @param string $head Section header
  7043. * @param string $short_string A short description
  7044. * @param string $long_string A long (more detailed) description
  7045. * @param integer $type -1=OK sign, 0=message, 1=notification, 2=warning, 3=error
  7046. * @param boolean $force Print message also in "Advanced" mode (not only in 1-2-3 mode)
  7047. * @return void
  7048. */
  7049. function message($head, $short_string='', $long_string='', $type=0, $force=0) {
  7050. // Return directly if mode-123 is enabled.
  7051. if (!$force && $this->mode=='123' && $type<2) {
  7052. return;
  7053. }
  7054. if ($type==3) { $this->fatalError=1; }
  7055. $long_string = trim($long_string);
  7056. if (!$this->silent) $this->printSection($head, $short_string, $long_string, $type);
  7057. }
  7058. /**
  7059. * This "prints" a section with a message to the ->sections array
  7060. *
  7061. * @param string $head Section header
  7062. * @param string $short_string A short description
  7063. * @param string $long_string A long (more detailed) description
  7064. * @param integer $type -1=OK sign, 0=message, 1=notification, 2=warning , 3=error
  7065. * @return void
  7066. */
  7067. function printSection($head, $short_string, $long_string, $type) {
  7068. // Get the template file
  7069. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'PrintSection.html');
  7070. // Get the template part from the file
  7071. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  7072. switch($type) {
  7073. case 3:
  7074. $messageType = 'message-error';
  7075. break;
  7076. case 2:
  7077. $messageType = 'message-warning';
  7078. break;
  7079. case 1:
  7080. $messageType = 'message-notice';
  7081. break;
  7082. case 0:
  7083. $messageType = 'message-information';
  7084. break;
  7085. case -1:
  7086. $messageType = 'message-ok';
  7087. break;
  7088. }
  7089. if (!trim($short_string)) {
  7090. $content = '';
  7091. } else {
  7092. if (trim($long_string)) {
  7093. // Get the subpart for the long string
  7094. $longStringSubpart = t3lib_parsehtml::getSubpart($template, '###LONGSTRINGAVAILABLE###');
  7095. }
  7096. // Substitute the subpart for the long string
  7097. $content = t3lib_parsehtml::substituteSubpart(
  7098. $template,
  7099. '###LONGSTRINGAVAILABLE###',
  7100. $longStringSubpart
  7101. );
  7102. // Define the markers content
  7103. $markers = array(
  7104. 'messageType' => $messageType,
  7105. 'shortString' => $short_string,
  7106. 'longString' => $long_string
  7107. );
  7108. // Fill the markers
  7109. $content = t3lib_parsehtml::substituteMarkerArray(
  7110. $content,
  7111. $markers,
  7112. '###|###',
  7113. TRUE,
  7114. FALSE
  7115. );
  7116. }
  7117. $this->sections[$head][] = $content;
  7118. }
  7119. /**
  7120. * This prints all the messages in the ->section array
  7121. *
  7122. * @return string HTML of all the messages
  7123. */
  7124. function printAll() {
  7125. // Get the template file
  7126. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'PrintAll.html');
  7127. // Get the template part from the file
  7128. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  7129. $sections = array();
  7130. foreach ($this->sections as $header => $valArray) {
  7131. // Get the subpart for sections
  7132. $sectionSubpart = t3lib_parsehtml::getSubpart($template, '###SECTIONS###');
  7133. // Define the markers content
  7134. $sectionMarkers = array(
  7135. 'header' => $header . ':',
  7136. 'sectionContent' => implode(LF, $valArray)
  7137. );
  7138. // Fill the markers in the subpart
  7139. $sections[] = t3lib_parsehtml::substituteMarkerArray(
  7140. $sectionSubpart,
  7141. $sectionMarkers,
  7142. '###|###',
  7143. TRUE,
  7144. FALSE
  7145. );
  7146. }
  7147. // Substitute the subpart for the sections
  7148. $content = t3lib_parsehtml::substituteSubpart(
  7149. $template,
  7150. '###SECTIONS###',
  7151. implode(LF, $sections)
  7152. );
  7153. return $content;
  7154. }
  7155. /**
  7156. * This wraps and returns the main content of the page into proper html-code.
  7157. *
  7158. * @param string $content The page content
  7159. * @return string The full HTML page
  7160. */
  7161. function outputWrapper($content) {
  7162. // Get the template file
  7163. if (!$this->passwordOK) {
  7164. $this->template = @file_get_contents(PATH_site . $this->templateFilePath . 'Install_login.html');
  7165. } elseif ($this->mode == '123') {
  7166. $this->template = @file_get_contents(PATH_site . $this->templateFilePath . 'Install_123.html');
  7167. } else {
  7168. $this->template = @file_get_contents(PATH_site . $this->templateFilePath . 'Install.html');
  7169. }
  7170. // Add prototype to javascript array for output
  7171. $this->javascript[] = '<script type="text/javascript" src="' .
  7172. t3lib_div::createVersionNumberedFilename(
  7173. '../contrib/prototype/prototype.js'
  7174. ) . '"></script>';
  7175. // Add JS functions for output
  7176. $this->javascript[] = '<script type="text/javascript" src="' .
  7177. t3lib_div::createVersionNumberedFilename(
  7178. '../sysext/install/Resources/Public/Javascript/install.js'
  7179. ) . '"></script>';
  7180. // Include the default stylesheets
  7181. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7182. t3lib_div::createVersionNumberedFilename($this->backPath .
  7183. 'sysext/install/Resources/Public/Stylesheets/reset.css'
  7184. ) . '" />';
  7185. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7186. t3lib_div::createVersionNumberedFilename($this->backPath .
  7187. 'sysext/install/Resources/Public/Stylesheets/general.css'
  7188. ) . '" />';
  7189. // Get the browser info
  7190. $browserInfo = t3lib_utility_Client::getBrowserInfo(t3lib_div::getIndpEnv('HTTP_USER_AGENT'));
  7191. // Add the stylesheet for Internet Explorer
  7192. if ($browserInfo['browser'] === 'msie') {
  7193. // IE7
  7194. if (intval($browserInfo['version']) === 7) {
  7195. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7196. t3lib_div::createVersionNumberedFilename($this->backPath .
  7197. 'sysext/install/Resources/Public/Stylesheets/ie7.css'
  7198. ) . '" />';
  7199. }
  7200. }
  7201. // Include the stylesheets based on screen
  7202. if ($this->mode == '123') {
  7203. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7204. t3lib_div::createVersionNumberedFilename($this->backPath .
  7205. 'sysext/install/Resources/Public/Stylesheets/install_123.css'
  7206. ) . '" />';
  7207. } elseif ($this->passwordOK) {
  7208. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7209. t3lib_div::createVersionNumberedFilename($this->backPath .
  7210. 'sysext/install/Resources/Public/Stylesheets/install.css'
  7211. ) . '" />';
  7212. } else {
  7213. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7214. t3lib_div::createVersionNumberedFilename($this->backPath .
  7215. 'sysext/install/Resources/Public/Stylesheets/install.css'
  7216. ) . '" />';
  7217. $this->stylesheets[] = '<link rel="stylesheet" type="text/css" href="' .
  7218. t3lib_div::createVersionNumberedFilename($this->backPath .
  7219. 'sysext/install/Resources/Public/Stylesheets/install_login.css'
  7220. ) . '" />';
  7221. }
  7222. // Define the markers content
  7223. if ($this->mode == '123') {
  7224. $this->markers['headTitle'] = 'Installing TYPO3 ' . TYPO3_branch;
  7225. } else {
  7226. $this->markers['headTitle'] = '
  7227. TYPO3 ' . TYPO3_version . '
  7228. Install Tool on site: ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) . '
  7229. ';
  7230. }
  7231. $this->markers['title'] = 'TYPO3 ' . TYPO3_version;
  7232. $this->markers['javascript'] = implode(LF, $this->javascript);
  7233. $this->markers['stylesheets'] = implode(LF, $this->stylesheets);
  7234. $this->markers['llErrors'] = 'The following errors occured';
  7235. $this->markers['copyright'] = $this->copyright();
  7236. $this->markers['charset'] = 'utf-8';
  7237. $this->markers['backendUrl'] = '../index.php';
  7238. $this->markers['backend'] = 'Backend admin';
  7239. $this->markers['frontendUrl'] = '../../index.php';
  7240. $this->markers['frontend'] = 'Frontend website';
  7241. $this->markers['metaCharset'] = 'Content-Type" content="text/html; charset=';
  7242. $this->markers['metaCharset'] .= 'utf-8';
  7243. // Add the error messages
  7244. if (!empty($this->errorMessages)) {
  7245. // Get the subpart for all error messages
  7246. $errorMessagesSubPart = t3lib_parsehtml::getSubpart($this->template, '###ERRORMESSAGES###');
  7247. // Get the subpart for a single error message
  7248. $errorMessageSubPart = t3lib_parsehtml::getSubpart($errorMessagesSubPart, '###MESSAGES###');
  7249. $errors = array();
  7250. foreach ($this->errorMessages as $errorMessage) {
  7251. // Define the markers content
  7252. $errorMessageMarkers = array(
  7253. 'message' => $errorMessage
  7254. );
  7255. // Fill the markers in the subpart
  7256. $errors[] = t3lib_parsehtml::substituteMarkerArray(
  7257. $errorMessageSubPart,
  7258. $errorMessageMarkers,
  7259. '###|###',
  7260. TRUE,
  7261. FALSE
  7262. );
  7263. }
  7264. // Substitute the subpart for a single message
  7265. $errorMessagesSubPart = t3lib_parsehtml::substituteSubpart(
  7266. $errorMessagesSubPart,
  7267. '###MESSAGES###',
  7268. implode(LF, $errors)
  7269. );
  7270. }
  7271. // Version subpart is only allowed when password is ok
  7272. if ($this->passwordOK) {
  7273. // Get the subpart for the version
  7274. $versionSubPart = t3lib_parsehtml::getSubpart($this->template, '###VERSIONSUBPART###');
  7275. // Define the markers content
  7276. $versionSubPartMarkers['version'] = 'Version: ' . TYPO3_version;
  7277. // Fill the markers in the subpart
  7278. $versionSubPart = t3lib_parsehtml::substituteMarkerArray(
  7279. $versionSubPart,
  7280. $versionSubPartMarkers,
  7281. '###|###',
  7282. TRUE,
  7283. FALSE
  7284. );
  7285. }
  7286. // Substitute the version subpart
  7287. $this->template = t3lib_parsehtml::substituteSubpart(
  7288. $this->template,
  7289. '###VERSIONSUBPART###',
  7290. $versionSubPart
  7291. );
  7292. // Substitute the menu subpart
  7293. $this->template = t3lib_parsehtml::substituteSubpart(
  7294. $this->template,
  7295. '###MENU###',
  7296. $this->menu()
  7297. );
  7298. // Substitute the error messages subpart
  7299. $this->template = t3lib_parsehtml::substituteSubpart(
  7300. $this->template,
  7301. '###ERRORMESSAGES###',
  7302. $errorMessagesSubPart
  7303. );
  7304. // Substitute the content subpart
  7305. $this->template = t3lib_parsehtml::substituteSubpart(
  7306. $this->template,
  7307. '###CONTENT###',
  7308. $content
  7309. );
  7310. // Fill the markers
  7311. $this->template = t3lib_parsehtml::substituteMarkerArray(
  7312. $this->template,
  7313. $this->markers,
  7314. '###|###',
  7315. TRUE,
  7316. FALSE
  7317. );
  7318. return $this->template;
  7319. }
  7320. /**
  7321. * Outputs an error and dies.
  7322. * Should be used by all errors that occur before even starting the install tool process.
  7323. *
  7324. * @param string The content of the error
  7325. * @return void
  7326. */
  7327. protected function outputErrorAndExit($content, $title = 'Install Tool error') {
  7328. // Define the stylesheet
  7329. $stylesheet = '<link rel="stylesheet" type="text/css" href="' .
  7330. '../stylesheets/install/install.css" />';
  7331. $javascript = '<script type="text/javascript" src="' .
  7332. '../contrib/prototype/prototype.js"></script>' . LF;
  7333. $javascript .= '<script type="text/javascript" src="' .
  7334. '../sysext/install/Resources/Public/Javascript/install.js"></script>';
  7335. // Get the template file
  7336. $template = @file_get_contents(PATH_site . '/typo3/templates/install.html');
  7337. // Define the markers content
  7338. $markers = array(
  7339. 'styleSheet' => $stylesheet,
  7340. 'javascript' => $javascript,
  7341. 'title' => $title,
  7342. 'content' => $content,
  7343. );
  7344. // Fill the markers
  7345. $content = t3lib_parsehtml::substituteMarkerArray(
  7346. $template,
  7347. $markers,
  7348. '###|###',
  7349. 1,
  7350. 1
  7351. );
  7352. // Output the warning message and exit
  7353. header('Content-Type: text/html; charset=utf-8');
  7354. header('Cache-Control: no-cache, must-revalidate');
  7355. header('Pragma: no-cache');
  7356. echo $content;
  7357. exit();
  7358. }
  7359. /**
  7360. * Sends the page to the client.
  7361. *
  7362. * @param string $content The HTML page
  7363. * @return void
  7364. */
  7365. function output($content) {
  7366. header ('Content-Type: text/html; charset=utf-8');
  7367. echo $content;
  7368. }
  7369. /**
  7370. * Generates the main menu
  7371. *
  7372. * @return string HTML of the main menu
  7373. */
  7374. function menu() {
  7375. if ($this->mode !='123') {
  7376. if (!$this->passwordOK) return;
  7377. $c = 0;
  7378. $items = array();
  7379. // Get the subpart for the main menu
  7380. $menuSubPart = t3lib_parsehtml::getSubpart($this->template, '###MENU###');
  7381. // Get the subpart for each single menu item
  7382. $menuItemSubPart = t3lib_parsehtml::getSubpart($this->template, '###MENUITEM###');
  7383. foreach ($this->menuitems as $k => $v) {
  7384. // Define the markers content
  7385. $markers = array(
  7386. 'class' => ($this->INSTALL['type']==$k ? 'class="act"' : ''),
  7387. 'id' => 't3-install-menu-' . $k,
  7388. 'url' => htmlspecialchars(
  7389. $this->scriptSelf .
  7390. '?TYPO3_INSTALL[type]=' .
  7391. $k .
  7392. ($this->mode ? '&mode=' . rawurlencode($this->mode) : '')
  7393. ),
  7394. 'item' => $v
  7395. );
  7396. // Fill the markers in the subpart
  7397. $items[] = t3lib_parsehtml::substituteMarkerArray(
  7398. $menuItemSubPart,
  7399. $markers,
  7400. '###|###',
  7401. TRUE,
  7402. FALSE
  7403. );
  7404. }
  7405. // Substitute the subpart for the single menu items
  7406. $menuSubPart = t3lib_parsehtml::substituteSubpart(
  7407. $menuSubPart,
  7408. '###MENUITEM###',
  7409. implode(LF, $items)
  7410. );
  7411. return $menuSubPart;
  7412. }
  7413. }
  7414. /**
  7415. * Generates the step header for 1-2-3 mode, the numbers at the top
  7416. *
  7417. * @return string HTML for the step header
  7418. */
  7419. function stepHeader() {
  7420. // Get the template file
  7421. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'StepHeader.html');
  7422. // Get the template part from the file
  7423. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  7424. // Get the subpart for each item
  7425. $stepItemSubPart = t3lib_parsehtml::getSubpart($template, '###STEPITEM###');
  7426. $steps = array();
  7427. for ($counter = 2; $counter <= $this->totalSteps; $counter++) {
  7428. $state = '';
  7429. if ($this->step === $counter) {
  7430. $state = 'act';
  7431. } elseif ($this->step === 'go' || $counter < $this->step) {
  7432. $state = 'done';
  7433. }
  7434. // Define the markers content
  7435. $stepItemMarkers = array(
  7436. 'class' => 'class="step' . ($counter - 1) . ($state ? ' ' . $state : '') . '"',
  7437. 'url' => $this->scriptSelf . '?mode=' . $this->mode . '&amp;step=' . $counter,
  7438. 'step' => $counter
  7439. );
  7440. // Fill the markers in the subpart
  7441. $steps[] = t3lib_parsehtml::substituteMarkerArray(
  7442. $stepItemSubPart,
  7443. $stepItemMarkers,
  7444. '###|###',
  7445. TRUE,
  7446. FALSE
  7447. );
  7448. }
  7449. // Substitute the subpart for the items
  7450. $content = t3lib_parsehtml::substituteSubpart(
  7451. $template,
  7452. '###STEPITEM###',
  7453. implode(LF, $steps)
  7454. );
  7455. return $content;
  7456. }
  7457. /**
  7458. * Generate HTML for the security risk message
  7459. *
  7460. * @return string HTML for the security risk message
  7461. */
  7462. function securityRisk() {
  7463. return '
  7464. <p>
  7465. <strong>An unsecured Install Tool presents a security risk.</strong>
  7466. Minimize the risk with the following actions:
  7467. </p>
  7468. <ul>
  7469. <li>
  7470. Change the Install Tool password.
  7471. </li>
  7472. <li>
  7473. Delete the ENABLE_INSTALL_TOOL file in the /typo3conf folder. This can be done
  7474. manually or through User tools &gt; User settings in the backend.
  7475. </li>
  7476. <li>
  7477. For additional security, the /typo3/install/ folder can be
  7478. renamed, deleted, or password protected with a .htaccess file.
  7479. </li>
  7480. </ul>
  7481. ';
  7482. }
  7483. /**
  7484. * Generates the form to alter the password of the Install Tool
  7485. *
  7486. * @return string HTML of the form
  7487. */
  7488. function alterPasswordForm() {
  7489. // Get the template file
  7490. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'AlterPasswordForm.html');
  7491. // Get the template part from the file
  7492. $template = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  7493. // Define the markers content
  7494. $markers = array(
  7495. 'action' => $this->scriptSelf.'?TYPO3_INSTALL[type]=extConfig',
  7496. 'enterPassword' => 'Enter new password:',
  7497. 'enterAgain' => 'Enter again:',
  7498. 'submit' => 'Set new password',
  7499. 'formToken' => $this->formProtection->generateToken(
  7500. 'installToolPassword', 'change'
  7501. ),
  7502. );
  7503. // Fill the markers
  7504. $content = t3lib_parsehtml::substituteMarkerArray(
  7505. $template,
  7506. $markers,
  7507. '###|###',
  7508. TRUE,
  7509. FALSE
  7510. );
  7511. return $content;
  7512. }
  7513. /**
  7514. * Generate HTML for the copyright
  7515. *
  7516. * @return string HTML of the copyright
  7517. */
  7518. function copyright() {
  7519. $content = '
  7520. <p>
  7521. <strong>TYPO3 CMS.</strong> Copyright &copy; 1998-' . date('Y') . '
  7522. Kasper Sk&#229;rh&#248;j. Extensions are copyright of their respective
  7523. owners. Go to <a href="' . TYPO3_URL_GENERAL . '">' . TYPO3_URL_GENERAL . '</a>
  7524. for details. TYPO3 comes with ABSOLUTELY NO WARRANTY;
  7525. <a href="' . TYPO3_URL_LICENSE . '">click</a> for details.
  7526. This is free software, and you are welcome to redistribute it
  7527. under certain conditions; <a href="' . TYPO3_URL_LICENSE . '">click</a>
  7528. for details. Obstructing the appearance of this notice is prohibited by law.
  7529. </p>
  7530. <p>
  7531. <a href="' . TYPO3_URL_DONATE . '"><strong>Donate</strong></a> |
  7532. <a href="' . TYPO3_URL_ORG . '">TYPO3.org</a>
  7533. </p>
  7534. ';
  7535. return $content;
  7536. }
  7537. /**
  7538. * Generate HTML for the message that the basic setup has been finished
  7539. *
  7540. * @return string HTML of the message
  7541. */
  7542. function messageBasicFinished() {
  7543. return '
  7544. <p>
  7545. You have completed the basic setup of the TYPO3 Content Management System.
  7546. Choose between these options to continue:
  7547. </p>
  7548. <ul>
  7549. <li>
  7550. <a href="' . $this->scriptSelf . '">Configure TYPO3</a> (Recommended)
  7551. <br />
  7552. This will let you analyze and verify that everything in your
  7553. installation is in order. In addition, you can configure advanced
  7554. TYPO3 options in this step.
  7555. </li>
  7556. <li>
  7557. <a href="../../index.php">
  7558. Visit the frontend
  7559. </a>
  7560. </li>
  7561. <li>
  7562. <a href="../index.php">
  7563. Login to the backend
  7564. </a>
  7565. <br />
  7566. (Default username: <em>admin</em>, default password: <em>password</em>.)
  7567. </li>
  7568. </ul>
  7569. ';
  7570. }
  7571. /**
  7572. * Make the url of the script according to type, mode and step
  7573. *
  7574. * @param string $type The type
  7575. * @return string The url
  7576. */
  7577. function setScriptName($type) {
  7578. $value = $this->scriptSelf.'?TYPO3_INSTALL[type]='.$type.($this->mode?'&mode='.rawurlencode($this->mode):'').($this->step?'&step='.rawurlencode($this->step):'');
  7579. return $value;
  7580. }
  7581. /**
  7582. * Return the filename that will be used for the backup.
  7583. * It is important that backups of PHP files still stay as a PHP file, otherwise they could be viewed un-parsed in clear-text.
  7584. *
  7585. * @param string $filename Full path to a file
  7586. * @return string The name of the backup file (again, including the full path)
  7587. */
  7588. function getBackupFilename($filename) {
  7589. if (preg_match('/\.php$/', $filename)) {
  7590. $backupFile = str_replace('.php', '_bak.php', $filename);
  7591. } else {
  7592. $backupFile = $filename.'~';
  7593. }
  7594. return $backupFile;
  7595. }
  7596. /**
  7597. * Creates a table which checkboxes for updating database.
  7598. *
  7599. * @param array $arr Array of statements (key / value pairs where key is used for the checkboxes)
  7600. * @param string $label Label for the table.
  7601. * @param boolean $checked If set, then checkboxes are set by default.
  7602. * @param boolean $iconDis If set, then icons are shown.
  7603. * @param array $currentValue Array of "current values" for each key/value pair in $arr. Shown if given.
  7604. * @param boolean $cVfullMsg If set, will show the prefix "Current value" if $currentValue is given.
  7605. * @return string HTML table with checkboxes for update. Must be wrapped in a form.
  7606. */
  7607. function generateUpdateDatabaseForm_checkboxes($arr, $label, $checked=1, $iconDis=0, $currentValue=array(), $cVfullMsg=0) {
  7608. $out = array();
  7609. $tableId = uniqid('table');
  7610. $templateMarkers = array();
  7611. if (is_array($arr)) {
  7612. // Get the template file
  7613. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'GenerateUpdateDatabaseFormCheckboxes.html');
  7614. // Get the template part from the file
  7615. $content = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  7616. // Define the markers content
  7617. $templateMarkers = array(
  7618. 'label' => $label,
  7619. 'tableId' => $tableId
  7620. );
  7621. // Select/Deselect All
  7622. if (count($arr) > 1) {
  7623. // Get the subpart for multiple tables
  7624. $multipleTablesSubpart = t3lib_parsehtml::getSubpart($content, '###MULTIPLETABLES###');
  7625. // Define the markers content
  7626. $multipleTablesMarkers = array(
  7627. 'label' => $label,
  7628. 'tableId' => $tableId,
  7629. 'checked' => ($checked ? ' checked="checked"' : ''),
  7630. 'selectAllId' => 't3-install-' . $tableId . '-checkbox',
  7631. 'selectDeselectAll' => 'select/deselect all'
  7632. );
  7633. // Fill the markers in the subpart
  7634. $multipleTablesSubpart = t3lib_parsehtml::substituteMarkerArray(
  7635. $multipleTablesSubpart,
  7636. $multipleTablesMarkers,
  7637. '###|###',
  7638. TRUE,
  7639. FALSE
  7640. );
  7641. }
  7642. // Substitute the subpart for multiple tables
  7643. $content = t3lib_parsehtml::substituteSubpart(
  7644. $content,
  7645. '###MULTIPLETABLES###',
  7646. $multipleTablesSubpart
  7647. );
  7648. // Rows
  7649. foreach ($arr as $key => $string) {
  7650. // Get the subpart for rows
  7651. $rowsSubpart = t3lib_parsehtml::getSubpart($content, '###ROWS###');
  7652. $currentSubpart = '';
  7653. $ico = '';
  7654. $warnings = array();
  7655. // Define the markers content
  7656. $rowsMarkers = array(
  7657. 'checkboxId' => 't3-install-db-' . $key,
  7658. 'name' => $this->dbUpdateCheckboxPrefix . '[' . $key . ']',
  7659. 'checked' => ($checked ? 'checked="checked"' : ''),
  7660. 'string' => htmlspecialchars($string)
  7661. );
  7662. if ($iconDis) {
  7663. $iconMarkers['backPath'] = $this->backPath;
  7664. if (preg_match('/^TRUNCATE/i', $string)) {
  7665. $iconMarkers['iconText'] = '';
  7666. $warnings['clear_table_info'] = 'Clearing the table is sometimes neccessary when adding new keys. In case of cache_* tables this should not hurt at all. However, use it with care.';
  7667. } elseif (stristr($string, ' user_')) {
  7668. $iconMarkers['iconText'] = '(USER)';
  7669. } elseif (stristr($string, ' app_')) {
  7670. $iconMarkers['iconText'] = '(APP)';
  7671. } elseif (stristr($string, ' ttx_') || stristr($string, ' tx_')) {
  7672. $iconMarkers['iconText'] = '(EXT)';
  7673. }
  7674. if (!empty($iconMarkers)) {
  7675. // Get the subpart for icons
  7676. $iconSubpart = t3lib_parsehtml::getSubpart($content, '###ICONAVAILABLE###');
  7677. // Fill the markers in the subpart
  7678. $iconSubpart = t3lib_parsehtml::substituteMarkerArray(
  7679. $iconSubpart,
  7680. $iconMarkers,
  7681. '###|###',
  7682. TRUE,
  7683. TRUE
  7684. );
  7685. }
  7686. }
  7687. // Substitute the subpart for icons
  7688. $rowsSubpart = t3lib_parsehtml::substituteSubpart(
  7689. $rowsSubpart,
  7690. '###ICONAVAILABLE###',
  7691. $iconSubpart
  7692. );
  7693. if (isset($currentValue[$key])) {
  7694. // Get the subpart for current
  7695. $currentSubpart = t3lib_parsehtml::getSubpart($rowsSubpart, '###CURRENT###');
  7696. // Define the markers content
  7697. $currentMarkers = array (
  7698. 'message' => (!$cVfullMsg ? 'Current value:': ''),
  7699. 'value' => $currentValue[$key]
  7700. );
  7701. // Fill the markers in the subpart
  7702. $currentSubpart = t3lib_parsehtml::substituteMarkerArray(
  7703. $currentSubpart,
  7704. $currentMarkers,
  7705. '###|###',
  7706. TRUE,
  7707. FALSE
  7708. );
  7709. }
  7710. // Substitute the subpart for current
  7711. $rowsSubpart = t3lib_parsehtml::substituteSubpart(
  7712. $rowsSubpart,
  7713. '###CURRENT###',
  7714. $currentSubpart
  7715. );
  7716. $errorSubpart = '';
  7717. if (isset($this->databaseUpdateErrorMessages[$key])) {
  7718. // Get the subpart for current
  7719. $errorSubpart = t3lib_parsehtml::getSubpart($rowsSubpart, '###ERROR###');
  7720. // Define the markers content
  7721. $currentMarkers = array (
  7722. 'errorMessage' => $this->databaseUpdateErrorMessages[$key],
  7723. );
  7724. // Fill the markers in the subpart
  7725. $errorSubpart = t3lib_parsehtml::substituteMarkerArray(
  7726. $errorSubpart,
  7727. $currentMarkers,
  7728. '###|###',
  7729. TRUE,
  7730. FALSE
  7731. );
  7732. }
  7733. // Substitute the subpart for error messages
  7734. $rowsSubpart = t3lib_parsehtml::substituteSubpart(
  7735. $rowsSubpart,
  7736. '###ERROR###',
  7737. $errorSubpart
  7738. );
  7739. // Fill the markers in the subpart
  7740. $rowsSubpart = t3lib_parsehtml::substituteMarkerArray(
  7741. $rowsSubpart,
  7742. $rowsMarkers,
  7743. '###|###',
  7744. TRUE,
  7745. FALSE
  7746. );
  7747. $rows[] = $rowsSubpart;
  7748. }
  7749. // Substitute the subpart for rows
  7750. $content = t3lib_parsehtml::substituteSubpart(
  7751. $content,
  7752. '###ROWS###',
  7753. implode(LF, $rows)
  7754. );
  7755. if (count($warnings)) {
  7756. // Get the subpart for warnings
  7757. $warningsSubpart = t3lib_parsehtml::getSubpart($content, '###WARNINGS###');
  7758. $warningItems = array();
  7759. foreach ($warnings as $warning) {
  7760. // Get the subpart for single warning items
  7761. $warningItemSubpart = t3lib_parsehtml::getSubpart($warningsSubpart, '###WARNINGITEM###');
  7762. // Define the markers content
  7763. $warningItemMarker['warning'] = $warning;
  7764. // Fill the markers in the subpart
  7765. $warningItems[] = t3lib_parsehtml::substituteMarkerArray(
  7766. $warningItemSubpart,
  7767. $warningItemMarker,
  7768. '###|###',
  7769. TRUE,
  7770. FALSE
  7771. );
  7772. }
  7773. // Substitute the subpart for single warning items
  7774. $warningsSubpart = t3lib_parsehtml::substituteSubpart(
  7775. $warningsSubpart,
  7776. '###WARNINGITEM###',
  7777. implode(LF, $warningItems)
  7778. );
  7779. }
  7780. // Substitute the subpart for warnings
  7781. $content = t3lib_parsehtml::substituteSubpart(
  7782. $content,
  7783. '###WARNINGS###',
  7784. $warningsSubpart
  7785. );
  7786. }
  7787. // Fill the markers
  7788. $content = t3lib_parsehtml::substituteMarkerArray(
  7789. $content,
  7790. $templateMarkers,
  7791. '###|###',
  7792. TRUE,
  7793. FALSE
  7794. );
  7795. return $content;
  7796. }
  7797. /**
  7798. * Returns HTML-code, which is a visual representation of a multidimensional array
  7799. * Returns FALSE if $array_in is not an array
  7800. *
  7801. * @param mixed $incomingValue Array to view
  7802. * @return string HTML output
  7803. */
  7804. function viewArray($incomingValue) {
  7805. // Get the template file
  7806. $templateFile = @file_get_contents(PATH_site . $this->templateFilePath . 'ViewArray.html');
  7807. if (is_array($incomingValue) && !empty($incomingValue)) {
  7808. // Get the template part from the file
  7809. $content = t3lib_parsehtml::getSubpart($templateFile, '###TEMPLATE###');
  7810. // Get the subpart for a single item
  7811. $itemSubpart = t3lib_parsehtml::getSubpart($content, '###ITEM###');
  7812. foreach ($incomingValue as $key => $value) {
  7813. if (is_array($value)) {
  7814. $description = $this->viewArray($value);
  7815. } elseif (is_object($value)) {
  7816. $description = get_class($value);
  7817. if (method_exists($value, '__toString')) {
  7818. $description .= ': ' . (string)$value;
  7819. }
  7820. } else {
  7821. if (gettype($value) == 'object') {
  7822. $description = 'Unknown object';
  7823. } else {
  7824. $description = htmlspecialchars((string) $value);
  7825. }
  7826. }
  7827. // Define the markers content
  7828. $itemMarkers = array(
  7829. 'key' => htmlspecialchars((string) $key),
  7830. 'description' => !empty($description) ? $description : '&nbsp;'
  7831. );
  7832. // Fill the markers in the subpart
  7833. $items[] = t3lib_parsehtml::substituteMarkerArray(
  7834. $itemSubpart,
  7835. $itemMarkers,
  7836. '###|###',
  7837. TRUE,
  7838. FALSE
  7839. );
  7840. }
  7841. // Substitute the subpart for single item
  7842. $content = t3lib_parsehtml::substituteSubpart(
  7843. $content,
  7844. '###ITEM###',
  7845. implode(LF, $items)
  7846. );
  7847. }
  7848. return $content;
  7849. }
  7850. /**
  7851. * Returns a newly created TYPO3 encryption key with a given length.
  7852. *
  7853. * @param integer $keyLength Desired key length
  7854. * @return string The encryption key
  7855. */
  7856. public function createEncryptionKey($keyLength = 96) {
  7857. $bytes = t3lib_div::generateRandomBytes($keyLength);
  7858. return substr(bin2hex($bytes), -96);
  7859. }
  7860. /**
  7861. * Adds an error message that should be displayed.
  7862. *
  7863. * @param string $messageText
  7864. * the text of the message to display, must not be empty
  7865. */
  7866. public function addErrorMessage($messageText) {
  7867. if ($messageText == '') {
  7868. throw new InvalidArgumentException('$messageText must not be empty.', 1294587483);
  7869. }
  7870. $this->errorMessages[] = $messageText;
  7871. }
  7872. /**
  7873. * Checks whether the mysql user is allowed to create new databases.
  7874. *
  7875. * This code is adopted from the phpMyAdmin project
  7876. * http://www.phpmyadmin.net
  7877. *
  7878. * @return boolean
  7879. */
  7880. protected function checkCreateDatabasePrivileges() {
  7881. $createAllowed = FALSE;
  7882. $allowedPatterns = array();
  7883. $grants = $GLOBALS['TYPO3_DB']->sql_query('SHOW GRANTS');
  7884. // we get one or more lines like this
  7885. // insufficent rights:
  7886. // GRANT USAGE ON *.* TO 'test'@'localhost' IDENTIFIED BY ...
  7887. // GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'localhost'
  7888. // sufficient rights:
  7889. // GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY ...
  7890. // loop over all result rows
  7891. while (($row = $GLOBALS['TYPO3_DB']->sql_fetch_row($grants)) !== FALSE) {
  7892. $grant = $row[0];
  7893. $dbNameOffset = strpos($grant, ' ON ') + 4;
  7894. $dbName = substr($grant, $dbNameOffset, strpos($grant, '.', $dbNameOffset) - $dbNameOffset);
  7895. $privileges = substr($grant, 6, (strpos($grant, ' ON ') - 6));
  7896. // we need at least one of the following privileges
  7897. if ($privileges === 'ALL'
  7898. || $privileges === 'ALL PRIVILEGES'
  7899. || $privileges === 'CREATE'
  7900. || strpos($privileges, 'CREATE,') !== FALSE) {
  7901. // and we need this privelege not on a specific DB, but on *
  7902. if ($dbName === '*') {
  7903. // user has permissions to create new databases
  7904. $createAllowed = TRUE;
  7905. break;
  7906. } else {
  7907. $allowedPatterns[] = str_replace('`', '', $dbName);
  7908. }
  7909. }
  7910. }
  7911. // remove all existing databases from the list of allowed patterns
  7912. $existingDatabases = $this->getDatabaseList();
  7913. foreach ($allowedPatterns as $index => $pattern) {
  7914. if (strpos($pattern, '%') !== FALSE) continue;
  7915. if (in_array($pattern, $existingDatabases)) {
  7916. unset($allowedPatterns[$index]);
  7917. }
  7918. }
  7919. if (count($allowedPatterns) > 0) {
  7920. return $allowedPatterns;
  7921. } else {
  7922. return $createAllowed;
  7923. }
  7924. }
  7925. }
  7926. ?>