[TASK] Move t3lib/stddb/DefaultConfiguration.php to EXT:core
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Installer.php
1 <?php
2 namespace TYPO3\CMS\Install;
3
4 /**
5 * Install Tool module
6 *
7 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
8 * @author Ingmar Schlecht <ingmar@typo3.org>
9 */
10 class Installer {
11
12 /**
13 * @todo Define visibility
14 */
15 public $templateFilePath = 'typo3/sysext/install/Resources/Private/Templates/';
16
17 /**
18 * @todo Define visibility
19 */
20 public $template;
21
22 /**
23 * @todo Define visibility
24 */
25 public $javascript;
26
27 /**
28 * @todo Define visibility
29 */
30 public $stylesheets;
31
32 /**
33 * @todo Define visibility
34 */
35 public $markers = array();
36
37 /**
38 * Used to set (error)messages from the executing functions like mail-sending, writing Localconf and such
39 *
40 * @var array
41 */
42 protected $messages = array();
43
44 /**
45 * @todo Define visibility
46 */
47 public $errorMessages = array();
48
49 /**
50 * @todo Define visibility
51 */
52 public $mailMessage = '';
53
54 /**
55 * @todo Define visibility
56 */
57 public $action = '';
58
59 // The url that calls this script
60 /**
61 * @todo Define visibility
62 */
63 public $scriptSelf = 'index.php';
64
65 // The url that calls this script
66 /**
67 * @todo Define visibility
68 */
69 public $updateIdentity = 'TYPO3 Install Tool';
70
71 /**
72 * @todo Define visibility
73 */
74 public $headerStyle = '';
75
76 /**
77 * @todo Define visibility
78 */
79 public $setAllCheckBoxesByDefault = 0;
80
81 /**
82 * @todo Define visibility
83 */
84 public $allowFileEditOutsite_typo3conf_dir = 0;
85
86 /**
87 * @todo Define visibility
88 */
89 public $INSTALL = array();
90
91 // In constructor: is set to global GET/POST var TYPO3_INSTALL
92 /**
93 * @todo Define visibility
94 */
95 public $checkIMlzw = 0;
96
97 // If set, lzw capabilities of the available ImageMagick installs are check by actually writing a gif-file and comparing size
98 /**
99 * @todo Define visibility
100 */
101 public $checkIM = 0;
102
103 // If set, ImageMagick is checked.
104 /**
105 * @todo Define visibility
106 */
107 public $dumpImCommands = 1;
108
109 // If set, the image Magick commands are always outputted in the image processing checker
110 /**
111 * @todo Define visibility
112 */
113 public $mode = '';
114
115 // If set to "123" then only most vital information is displayed.
116 /**
117 * @todo Define visibility
118 */
119 public $step = 0;
120
121 // If set to 1,2,3 or GO it signifies various functions.
122 /**
123 * @todo Define visibility
124 */
125 public $totalSteps = 4;
126
127 /**
128 * @var boolean
129 */
130 protected $hasAdditionalSteps = FALSE;
131
132 // Can be changed by hook to define the total steps in 123 mode
133 // internal
134 /**
135 * @todo Define visibility
136 */
137 public $passwordOK = 0;
138
139 // This is set, if the password check was ok. The function init() will exit if this is not set
140 /**
141 * @todo Define visibility
142 */
143 public $silent = 1;
144
145 // If set, the check routines don't add to the message-array
146 /**
147 * @todo Define visibility
148 */
149 public $sections = array();
150
151 // Used to gather the message information.
152 /**
153 * @todo Define visibility
154 */
155 public $fatalError = 0;
156
157 // This is set if some error occured that will definitely prevent TYpo3 from running.
158 /**
159 * @todo Define visibility
160 */
161 public $sendNoCacheHeaders = 1;
162
163 /**
164 * @todo Define visibility
165 */
166 public $config_array = array(
167 // Flags are set in this array if the options are available and checked ok.
168 'gd' => 0,
169 'gd_gif' => 0,
170 'gd_png' => 0,
171 'gd_jpg' => 0,
172 'freetype' => 0,
173 'safemode' => 0,
174 'dir_typo3temp' => 0,
175 'dir_temp' => 0,
176 'im_versions' => array(),
177 'im' => 0,
178 'sql.safe_mode_user' => '',
179 'mysqlConnect' => 0,
180 'no_database' => 0
181 );
182
183 /**
184 * @todo Define visibility
185 */
186 public $typo3temp_path = '';
187
188 /**
189 * the session handling object
190 *
191 * @var \TYPO3\CMS\Install\Session
192 */
193 protected $session = NULL;
194
195 /**
196 * the form protection instance used for creating and verifying form tokens
197 *
198 * @var \TYPO3\CMS\Core\FormProtection\InstallToolFormProtection
199 */
200 protected $formProtection = NULL;
201
202 /**
203 * @todo Define visibility
204 */
205 public $menuitems = array(
206 'config' => 'Basic Configuration',
207 'database' => 'Database Analyser',
208 'update' => 'Upgrade Wizard',
209 'images' => 'Image Processing',
210 'extConfig' => 'All Configuration',
211 'cleanup' => 'Clean up',
212 'phpinfo' => 'phpinfo()',
213 'typo3conf_edit' => 'Edit files in typo3conf/',
214 'about' => 'About',
215 'logout' => 'Logout from Install Tool'
216 );
217
218 // PHP modules which are required. Can be changed by hook in getMissingPhpModules()
219 protected $requiredPhpModules = array(
220 'fileinfo',
221 'filter',
222 'gd',
223 'json',
224 'mysql',
225 'pcre',
226 'session',
227 'SPL',
228 'standard',
229 'openssl',
230 'xml',
231 'zlib'
232 );
233
234 /**
235 * Backpath (used for icons etc.)
236 *
237 * @var string
238 */
239 protected $backPath = '../';
240
241 /**
242 * @var \TYPO3\CMS\Install\Sql\SchemaMigrator Instance of SQL handler
243 */
244 protected $sqlHandler = NULL;
245
246 /**
247 * Prefix for checkbox fields when updating database.
248 *
249 * @var string
250 */
251 protected $dbUpdateCheckboxPrefix = 'TYPO3_INSTALL[database_update]';
252
253 /**
254 * Constructor
255 *
256 * @return void
257 * @todo Define visibility
258 */
259 public function __construct() {
260 $this->sqlHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Install\\Sql\\SchemaMigrator');
261
262 if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword']) {
263 $this->outputErrorAndExit('Install Tool deactivated.<br />
264 You must enable it by setting a password in typo3conf/LocalConfiguration.php. If you insert the value below at array position \'BE\' \'installToolPassword\', the password will be \'joh316\':<br /><br />
265 \'bacb98acf97e0b6112b1d1b650b84971\'', 'Fatal error');
266 }
267 if ($this->sendNoCacheHeaders) {
268 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
269 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
270 header('Expires: 0');
271 header('Cache-Control: no-cache, must-revalidate');
272 header('Pragma: no-cache');
273 }
274 // ****************************
275 // Initializing incoming vars.
276 // ****************************
277 $this->INSTALL = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('TYPO3_INSTALL');
278 $this->mode = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('mode');
279 if ($this->mode !== '123') {
280 $this->mode = '';
281 }
282 if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('step') === 'go') {
283 $this->step = 'go';
284 } else {
285 $this->step = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('step'));
286 }
287 // Let DBAL decide whether to load itself
288 $dbalLoaderFile = $this->backPath . 'sysext/dbal/class.tx_dbal_autoloader.php';
289 if (@is_file($dbalLoaderFile)) {
290 include $dbalLoaderFile;
291 }
292 if ($this->mode === '123') {
293 // Check for mandatory PHP modules
294 $missingPhpModules = $this->getMissingPhpModules();
295 if (count($missingPhpModules) > 0) {
296 throw new \RuntimeException(
297 'TYPO3 Installation Error: The following PHP module(s) is/are missing: "' .
298 implode('", "', $missingPhpModules) .
299 '". You need to install and enable these modules first to be able to install TYPO3.',
300 1294587482);
301 }
302 // Load saltedpasswords if possible
303 $saltedpasswordsLoaderFile = $this->backPath . 'sysext/saltedpasswords/classes/class.tx_saltedpasswords_autoloader.php';
304 if (@is_file($saltedpasswordsLoaderFile)) {
305 include $saltedpasswordsLoaderFile;
306 }
307 }
308 $this->redirect_url = \TYPO3\CMS\Core\Utility\GeneralUtility::sanitizeLocalUrl(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('redirect_url'));
309 $this->INSTALL['type'] = '';
310 if ($_GET['TYPO3_INSTALL']['type']) {
311 $allowedTypes = array(
312 'config',
313 'database',
314 'update',
315 'images',
316 'extConfig',
317 'cleanup',
318 'phpinfo',
319 'typo3conf_edit',
320 'about',
321 'logout'
322 );
323 if (in_array($_GET['TYPO3_INSTALL']['type'], $allowedTypes)) {
324 $this->INSTALL['type'] = $_GET['TYPO3_INSTALL']['type'];
325 }
326 }
327 if ($this->step == 4) {
328 $this->INSTALL['type'] = 'database';
329 }
330 // Hook to raise the counter for the total steps in the 1-2-3 installer
331 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['additionalSteps'])) {
332 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['additionalSteps'] as $classData) {
333 $hookObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classData);
334 $additionalSteps = (int) $hookObject->executeAdditionalSteps($this);
335
336 if ($additionalSteps > 0) {
337 $this->hasAdditionalSteps = TRUE;
338 }
339
340 $this->totalSteps += $additionalSteps;
341 }
342 }
343 if ($this->mode == '123') {
344 $tempItems = $this->menuitems;
345 $this->menuitems = array(
346 'config' => $tempItems['config'],
347 'database' => $tempItems['database']
348 );
349 if (!$this->INSTALL['type'] || !isset($this->menuitems[$this->INSTALL['type']])) {
350 $this->INSTALL['type'] = 'config';
351 }
352 } else {
353 if (!$this->INSTALL['type'] || !isset($this->menuitems[$this->INSTALL['type']])) {
354 $this->INSTALL['type'] = 'about';
355 }
356 }
357 $this->action = $this->scriptSelf . '?TYPO3_INSTALL[type]=' . $this->INSTALL['type'] . ($this->mode ? '&mode=' . $this->mode : '') . ($this->step ? '&step=' . $this->step : '');
358 $this->typo3temp_path = PATH_site . 'typo3temp/';
359 if (!is_dir($this->typo3temp_path) || !is_writeable($this->typo3temp_path)) {
360 $this->outputErrorAndExit('Install Tool needs to write to typo3temp/. Make sure this directory is writeable by your webserver: ' . htmlspecialchars($this->typo3temp_path), 'Fatal error');
361 }
362 try {
363 $this->session = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_install_session');
364 } catch (\Exception $exception) {
365 $this->outputErrorAndExit($exception->getMessage());
366 }
367 // *******************
368 // Check authorization
369 // *******************
370 if (!$this->session->hasSession()) {
371 $this->session->startSession();
372 }
373 if ($this->session->isAuthorized() || $this->checkPassword()) {
374 $this->passwordOK = 1;
375 $this->session->refreshSession();
376 $enableInstallToolFile = PATH_typo3conf . 'ENABLE_INSTALL_TOOL';
377 if (is_file($enableInstallToolFile)) {
378 // Extend the age of the ENABLE_INSTALL_TOOL file by one hour
379 @touch($enableInstallToolFile);
380 }
381 if ($this->redirect_url) {
382 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->redirect_url);
383 }
384 $this->formProtection = \t3lib_formProtection_Factory::get('TYPO3\\CMS\\Core\\FormProtection\\InstallToolFormProtection');
385 $this->formProtection->injectInstallTool($this);
386 } else {
387 $this->loginForm();
388 }
389 }
390
391 /**
392 * Returns TRUE if submitted password is ok.
393 *
394 * If password is ok, set session as "authorized".
395 *
396 * @return boolean TRUE if the submitted password was ok and session was
397 * @todo Define visibility
398 */
399 public function checkPassword() {
400 $p = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('password');
401 if ($p && md5($p) === $GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword']) {
402 $this->session->setAuthorized();
403 // Sending warning email
404 $wEmail = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
405 if ($wEmail) {
406 $subject = 'Install Tool Login at "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '"';
407 $email_body = 'There has been an Install Tool login at TYPO3 site "' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '" (' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('HTTP_HOST') . ') from remote address "' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR') . '" (' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_HOST') . ')';
408 mail($wEmail, $subject, $email_body, 'From: TYPO3 Install Tool WARNING <>');
409 }
410 return TRUE;
411 } else {
412 // Bad password, send warning:
413 if ($p) {
414 $wEmail = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
415 if ($wEmail) {
416 $subject = 'Install Tool Login ATTEMPT at \'' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '\'';
417 $email_body = 'There has been an Install Tool login attempt at TYPO3 site \'' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '\' (' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('HTTP_HOST') . ').
418 The MD5 hash of the last 5 characters of the password tried was \'' . substr(md5($p), -5) . '\'
419 REMOTE_ADDR was \'' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR') . '\' (' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_HOST') . ')';
420 mail($wEmail, $subject, $email_body, 'From: TYPO3 Install Tool WARNING <>');
421 }
422 }
423 return FALSE;
424 }
425 }
426
427 /**
428 * Create the HTML for the login form
429 *
430 * Reads and fills the template.
431 * Substitutes subparts when wrong password has been given
432 * or the session has expired
433 *
434 * @return void
435 * @todo Define visibility
436 */
437 public function loginForm() {
438 $password = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('password');
439 $redirect_url = $this->redirect_url ? $this->redirect_url : $this->action;
440 // Get the template file
441 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'LoginForm.html'));
442 // Get the template part from the file
443 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
444 // Password has been given, but this form is rendered again.
445 // This means the given password was wrong
446 if (!empty($password)) {
447 // Get the subpart for the wrong password
448 $wrongPasswordSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###WRONGPASSWORD###');
449 // Define the markers content
450 $wrongPasswordMarkers = array(
451 'passwordMessage' => 'The password you just tried has this md5-value:',
452 'password' => md5($password)
453 );
454 // Fill the markers in the subpart
455 $wrongPasswordSubPart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($wrongPasswordSubPart, $wrongPasswordMarkers, '###|###', TRUE, TRUE);
456 }
457 // Session has expired
458 if (!$this->session->isAuthorized() && $this->session->isExpired()) {
459 // Get the subpart for the expired session message
460 $sessionExpiredSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###SESSIONEXPIRED###');
461 // Define the markers content
462 $sessionExpiredMarkers = array(
463 'message' => 'Your Install Tool session has expired'
464 );
465 // Fill the markers in the subpart
466 $sessionExpiredSubPart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($sessionExpiredSubPart, $sessionExpiredMarkers, '###|###', TRUE, TRUE);
467 }
468 // Substitute the subpart for the expired session in the template
469 $template = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###SESSIONEXPIRED###', $sessionExpiredSubPart);
470 // Substitute the subpart for the wrong password in the template
471 $template = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###WRONGPASSWORD###', $wrongPasswordSubPart);
472 // Define the markers content
473 $markers = array(
474 'siteName' => 'Site: ' . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']),
475 'headTitle' => 'Login to TYPO3 ' . TYPO3_version . ' Install Tool',
476 'redirectUrl' => htmlspecialchars($redirect_url),
477 'enterPassword' => 'Password',
478 'login' => 'Login',
479 'message' => '
480 <p class="typo3-message message-information">
481 The Install Tool Password is <em>not</em> the admin password
482 of TYPO3.
483 <br />
484 The default password is <em>joh316</em>. Be sure to change it!
485 <br /><br />
486 If you don\'t know the current password, you can set a new
487 one by setting the value of
488 $TYPO3_CONF_VARS[\'BE\'][\'installToolPassword\'] in
489 typo3conf/LocalConfiguration.php to the md5() hash value of the
490 password you desire.
491 </p>
492 '
493 );
494 // Fill the markers in the template
495 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markers, '###|###', TRUE, TRUE);
496 // Send content to the page wrapper function
497 $this->output($this->outputWrapper($content));
498 }
499
500 /**
501 * Calling function that checks system, IM, GD, dirs, database
502 * and lets you alter localconf.php
503 *
504 * This method is called from init.php to start the Install Tool.
505 *
506 * @return void
507 * @todo Define visibility
508 */
509 public function init() {
510 // Must be called after inclusion of init.php (or from init.php)
511 if (!defined('PATH_typo3')) {
512 die;
513 }
514 if (!$this->passwordOK) {
515 die;
516 }
517 // Setting stuff...
518 $this->check_mail();
519 $this->setupGeneral();
520 $this->generateConfigForm();
521 if (count($this->messages)) {
522 \TYPO3\CMS\Core\Utility\DebugUtility::debug($this->messages);
523 }
524 if ($this->step) {
525 $this->output($this->outputWrapper($this->stepOutput()));
526 } else {
527 // Menu...
528 switch ($this->INSTALL['type']) {
529 case 'images':
530 $this->checkIM = 1;
531 $this->checkTheConfig();
532 $this->silent = 0;
533 $this->checkTheImageProcessing();
534 break;
535 case 'database':
536 $this->checkTheConfig();
537 $this->silent = 0;
538 $this->checkTheDatabase();
539 break;
540 case 'update':
541 $this->checkDatabase();
542 $this->silent = 0;
543 $this->updateWizard();
544 break;
545 case 'config':
546 $this->silent = 0;
547 $this->checkIM = 1;
548 $this->message('About configuration', 'How to configure TYPO3', $this->generallyAboutConfiguration());
549 $isPhpCgi = PHP_SAPI == 'fpm-fcgi' || PHP_SAPI == 'cgi' || PHP_SAPI == 'isapi' || PHP_SAPI == 'cgi-fcgi';
550 $this->message('System Information', 'Your system has the following configuration', '
551 <dl id="systemInformation">
552 <dt>OS detected:</dt>
553 <dd>' . (TYPO3_OS == 'WIN' ? 'WIN' : 'UNIX') . '</dd>
554 <dt>CGI detected:</dt>
555 <dd>' . ($isPhpCgi ? 'YES' : 'NO') . '</dd>
556 <dt>PATH_thisScript:</dt>
557 <dd>' . PATH_thisScript . '</dd>
558 </dl>
559 ');
560 $this->checkTheConfig();
561 $ext = 'Write configuration';
562 if ($this->fatalError) {
563 if ($this->config_array['no_database'] || !$this->config_array['mysqlConnect']) {
564 $this->message($ext, 'Database not configured yet!', '
565 <p>
566 You need to specify database username,
567 password and host as one of the first things.
568 <br />
569 Next you\'ll have to select a database to
570 use with TYPO3.
571 </p>
572 <p>
573 Use the form below.
574 </p>
575 ', 2);
576 } else {
577 $this->message($ext, 'Fatal error encountered!', '
578 <p>
579 Somewhere above a fatal configuration
580 problem is encountered.
581 Please make sure that you\'ve fixed this
582 error before you submit the configuration.
583 TYPO3 will not run if this problem is not
584 fixed!
585 <br />
586 You should also check all warnings that may
587 appear.
588 </p>
589 ', 2);
590 }
591 } elseif ($this->mode == '123') {
592 if (!$this->fatalError) {
593 $this->message($ext, 'Basic configuration completed', '
594 <p>
595 You have no fatal errors in your basic
596 configuration.
597 You may have warnings though. Please pay
598 attention to them!
599 However you may continue and install the
600 database.
601 </p>
602 <p>
603 <strong>
604 <span style="color:#f00;">Step 2: </span>
605 </strong>
606 <a href="' . $this->scriptSelf . '?TYPO3_INSTALL[type]=database' . ($this->mode ? '&mode=' . rawurlencode($this->mode) : '') . '">Click here to install the database.</a>
607 </p>
608 ', -1, 1);
609 }
610 }
611 $this->message($ext, 'Very Important: Changing Image Processing settings', '
612 <p>
613 When you change the settings for Image Processing
614 you <em>must</em> take into account
615 that <em>old images</em> may still be in typo3temp/
616 folder and prevent new files from being generated!
617 <br />
618 This is especially important to know, if you\'re
619 trying to set up image processing for the very first
620 time.
621 <br />
622 The problem is solved by <a href="' . htmlspecialchars($this->setScriptName('cleanup')) . '">clearing the typo3temp/ folder</a>.
623 Also make sure to clear the cache_pages table.
624 </p>
625 ', 1, 1);
626 $this->message($ext, 'Very Important: Changing Encryption Key setting', '
627 <p>
628 When you change the setting for the Encryption Key
629 you <em>must</em> take into account that a change to
630 this value might invalidate temporary information,
631 URLs etc.
632 <br />
633 The problem is solved by <a href="' . htmlspecialchars($this->setScriptName('cleanup')) . '">clearing the typo3temp/ folder</a>.
634 Also make sure to clear the cache_pages table.
635 </p>
636 ', 1, 1);
637 $this->message($ext, 'Update configuration', '
638 <p>
639 This form updates the configuration with the
640 suggested values you see below. The values are based
641 on the analysis above.
642 <br />
643 You can change the values in case you have
644 alternatives to the suggested defaults.
645 <br />
646 By this final step you will configure TYPO3 for
647 immediate use provided that you have no fatal errors
648 left above.
649 </p>' . $this->setupGeneral('get_form') . '
650 ', 0, 1);
651 $this->output($this->outputWrapper($this->printAll()));
652 break;
653 case 'extConfig':
654 $this->silent = 0;
655 $this->generateConfigForm('get_form');
656 // Get the template file
657 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'InitExtConfig.html'));
658 // Get the template part from the file
659 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
660 // Define the markers content
661 $markers = array(
662 'action' => $this->action,
663 'content' => $this->printAll(),
664 'write' => 'Write configuration',
665 'notice' => 'NOTICE:',
666 'explanation' => '
667 By clicking this button, the configuration is updated
668 with new values for the parameters listed above!
669 '
670 );
671 // Fill the markers in the template
672 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markers, '###|###', TRUE, FALSE);
673 // Send content to the page wrapper function
674 $this->output($this->outputWrapper($content));
675 break;
676 case 'cleanup':
677 $this->checkTheConfig();
678 $this->silent = 0;
679 $this->cleanupManager();
680 break;
681 case 'phpinfo':
682 $this->silent = 0;
683 $this->phpinformation();
684 break;
685 case 'typo3conf_edit':
686 $this->silent = 0;
687 $this->typo3conf_edit();
688 break;
689 case 'logout':
690 $enableInstallToolFile = PATH_site . 'typo3conf/ENABLE_INSTALL_TOOL';
691 if (is_file($enableInstallToolFile) && trim(file_get_contents($enableInstallToolFile)) !== 'KEEP_FILE') {
692 unlink(PATH_typo3conf . 'ENABLE_INSTALL_TOOL');
693 }
694 $this->formProtection->clean();
695 $this->session->destroySession();
696 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->scriptSelf);
697 break;
698 case 'about':
699
700 default:
701 $this->silent = 0;
702 $this->message('About', 'Warning - very important!', $this->securityRisk() . $this->alterPasswordForm(), 2);
703 $this->message('About', 'Using this script', '
704 <p>
705 Installing TYPO3 has always been a hot topic on the
706 mailing list and forums. Therefore we\'ve developed
707 this tool which will help you through configuration
708 and testing.
709 <br />
710 There are three primary steps for you to take:
711 </p>
712 <p>
713 <strong>1: Basic Configuration</strong>
714 <br />
715 In this step your PHP-configuration is checked. If
716 there are any settings that will prevent TYPO3 from
717 running correctly you\'ll get warnings and errors
718 with a description of the problem.
719 <br />
720 You\'ll have to enter a database username, password
721 and hostname. Then you can choose to create a new
722 database or select an existing one.
723 <br />
724 Finally the image processing settings are entered
725 and verified and you can choose to let the script
726 update the configuration with the suggested settings.
727 </p>
728 <p>
729 <strong>2: Database Analyser</strong>
730 <br />
731 In this step you can either install a new database
732 or update the database from any previous TYPO3
733 version.
734 <br />
735 You can also get an overview of extra/missing
736 fields/tables in the database compared to a raw
737 sql-file.
738 <br />
739 The database is also verified against your
740 \'tables.php\' configuration ($TCA) and you can
741 even see suggestions to entries in $TCA or new
742 fields in the database.
743 </p>
744 <p>
745 <strong>3: Upgrade Wizard</strong>
746 <br />
747 Here you will find update methods taking care of
748 changes to the TYPO3 core which are not backwards
749 compatible.
750 <br />
751 It is recommended to run this wizard after every
752 update to make sure everything will still work
753 flawlessly.
754 </p>
755 <p>
756 <strong>4: Image Processing</strong>
757 <br />
758 This step is a visual guide to verify your
759 configuration of the image processing software.
760 <br />
761 You\'ll be presented to a list of images that should
762 all match in pairs. If some irregularity appears,
763 you\'ll get a warning. Thus you\'re able to track an
764 error before you\'ll discover it on your website.
765 </p>
766 <p>
767 <strong>5: All Configuration</strong>
768 <br />
769 This gives you access to any of the configuration
770 options in the TYPO3_CONF_VARS array. Every option
771 is also presented with a comment explaining what it
772 does.
773 </p>
774 <p>
775 <strong>6: Cleanup</strong>
776 <br />
777 Here you can clean up the temporary files in typo3temp/
778 folder and the tables used for caching of data in
779 your database.
780 </p>
781 ');
782 $this->message('About', 'Why is this script stand-alone?', '
783 <p>
784 You would think that this script should rather be a
785 module in the backend and access-controlled to only
786 admin-users from the database. But that\'s not how
787 it works.
788 <br />
789 The reason is, that this script must not be
790 depending on the success of the configuration of
791 TYPO3 and whether or not there is a working database
792 behind. Therefore the script is invoked from the
793 backend init.php file, which allows access if the
794 constant \'TYPO3_enterInstallScript\' has been
795 defined and is not FALSE. That is and should be the
796 case <em>only</em> when calling the script
797 \'typo3/install/index.php\' - this script!
798 </p>
799 ');
800 $headCode = 'Header legend';
801 $this->message($headCode, 'Notice!', '
802 <p>
803 Indicates that something is important to be aware
804 of.
805 <br />
806 This does <em>not</em> indicate an error.
807 </p>
808 ', 1);
809 $this->message($headCode, 'Just information', '
810 <p>
811 This is a simple message with some information about
812 something.
813 </p>
814 ');
815 $this->message($headCode, 'Check was successful', '
816 <p>
817 Indicates that something was checked and returned an
818 expected result.
819 </p>
820 ', -1);
821 $this->message($headCode, 'Warning!', '
822 <p>
823 Indicates that something may very well cause trouble
824 and you should definitely look into it before
825 proceeding.
826 <br />
827 This indicates a <em>potential</em> error.
828 </p>
829 ', 2);
830 $this->message($headCode, 'Error!', '
831 <p>
832 Indicates that something is definitely wrong and
833 that TYPO3 will most likely not perform as expected
834 if this problem is not solved.
835 <br />
836 This indicates an actual error.
837 </p>
838 ', 3);
839 $this->output($this->outputWrapper($this->printAll()));
840 break;
841 }
842 }
843 }
844
845 /**
846 * Controls the step 1-2-3-go process
847 *
848 * @return string The content to output to the screen
849 * @todo Define visibility
850 */
851 public function stepOutput() {
852 // Get the template file
853 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'StepOutput.html'));
854 // Get the template part from the file
855 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
856 // Define the markers content
857 $markers = array(
858 'stepHeader' => $this->stepHeader(),
859 'notice' => 'Skip this wizard (for power users only)',
860 'skip123' => $this->scriptSelf
861 );
862 $this->checkTheConfig();
863 $error_missingConnect = '
864 <p class="typo3-message message-error">
865 <strong>
866 There is no connection to the database!
867 </strong>
868 <br />
869 (Username: <em>' . htmlspecialchars(TYPO3_db_username) . '</em>,
870 Host: <em>' . htmlspecialchars(TYPO3_db_host) . '</em>,
871 Using Password: YES)
872 <br />
873 Go to Step 1 and enter a valid username and password!
874 </p>
875 ';
876 $error_missingDB = '
877 <p class="typo3-message message-error">
878 <strong>
879 There is no access to the database (<em>' . htmlspecialchars(TYPO3_db) . '</em>)!
880 </strong>
881 <br />
882 Go to Step 2 and select a valid database!
883 </p>
884 ';
885 // only get the number of tables if it is not the first two steps in the 123-installer
886 // (= no DB connection yet)
887 $whichTables = $this->step != 1 && $this->step != 2 ? $this->sqlHandler->getListOfTables() : array();
888 $error_emptyDB = '
889 <p class="typo3-message message-error">
890 <strong>
891 The database is still empty. There are no tables!
892 </strong>
893 <br />
894 Go to Step 3 and import a database!
895 </p>
896 ';
897 // Hook to override and add steps to the 1-2-3 installer
898 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['stepOutput'])) {
899 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install/mod/class.tx_install.php']['stepOutput'] as $classData) {
900 $hookObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classData);
901 $hookObject->executeStepOutput($markers, $this->step, $this);
902 }
903 }
904 // Use the default steps when there is no override
905 if (!$markers['header'] && !$markers['step']) {
906 switch (strtolower($this->step)) {
907 case 1:
908 // Get the subpart for the first step
909 $step1SubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEP1###');
910 // Add header marker for main template
911 $markers['header'] = 'Welcome to the TYPO3 Install Tool';
912 // Define the markers content for the subpart
913 $step1SubPartMarkers = array(
914 'llIntroduction' => '
915 <p>
916 TYPO3 is an enterprise content management system
917 that is powerful, yet easy to install.
918 </p>
919 <p>
920 In three simple steps you\'ll be ready to add content to your website.
921 </p>
922 ',
923 'step' => $this->step + 1,
924 'action' => htmlspecialchars($this->action),
925 'continue' => 'Continue'
926 );
927 // Add step marker for main template
928 $markers['step'] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($step1SubPart, $step1SubPartMarkers, '###|###', TRUE, FALSE);
929 break;
930 case 2:
931 // Get the subpart for the second step
932 $step2SubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEP2###');
933 // Add header marker for main template
934 $markers['header'] = 'Connect to your database host';
935 // Define the markers content for the subpart
936 $step2SubPartMarkers = array(
937 'step' => $this->step + 1,
938 'action' => htmlspecialchars($this->action),
939 'encryptionKey' => $this->createEncryptionKey(),
940 'branch' => TYPO3_branch,
941 'labelUsername' => 'Username',
942 'username' => htmlspecialchars(TYPO3_db_username),
943 'labelPassword' => 'Password',
944 'password' => htmlspecialchars(TYPO3_db_password),
945 'labelHost' => 'Host',
946 'host' => TYPO3_db_host ? htmlspecialchars(TYPO3_db_host) : 'localhost',
947 'continue' => 'Continue',
948 '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.'
949 );
950 // Add step marker for main template
951 $markers['step'] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($step2SubPart, $step2SubPartMarkers, '###|###', TRUE, FALSE);
952 break;
953 case 3:
954 // Add header marker for main template
955 $markers['header'] = 'Select database';
956 // There should be a database host connection at this point
957 if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
958 // Get the subpart for the third step
959 $step3SubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEP3###');
960 // Get the subpart for the database options
961 $step3DatabaseOptionsSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($step3SubPart, '###DATABASEOPTIONS###');
962 $dbArr = $this->getDatabaseList();
963 $dbIncluded = 0;
964 $step3DatabaseOptions = array();
965 foreach ($dbArr as $dbname) {
966 // Define the markers content for database options
967 $step3DatabaseOptionMarkers = array(
968 'databaseValue' => htmlspecialchars($dbname),
969 'databaseSelected' => $dbname == TYPO3_db ? 'selected="selected"' : '',
970 'databaseName' => htmlspecialchars($dbname)
971 );
972 // Add the option HTML to an array
973 $step3DatabaseOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($step3DatabaseOptionsSubPart, $step3DatabaseOptionMarkers, '###|###', TRUE, TRUE);
974 if ($dbname == TYPO3_db) {
975 $dbIncluded = 1;
976 }
977 }
978 if (!$dbIncluded && TYPO3_db) {
979 // // Define the markers content when no access
980 $step3DatabaseOptionMarkers = array(
981 'databaseValue' => htmlspecialchars(TYPO3_db),
982 'databaseSelected' => 'selected="selected"',
983 'databaseName' => htmlspecialchars(TYPO3_db) . ' (NO ACCESS!)'
984 );
985 // Add the option HTML to an array
986 $step3DatabaseOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($step3DatabaseOptionsSubPart, $step3DatabaseOptionMarkers, '###|###', TRUE, TRUE);
987 }
988 $usePatternList = FALSE;
989 $createDatabaseAllowed = $this->checkCreateDatabasePrivileges();
990 if ($createDatabaseAllowed === TRUE) {
991 $formFieldAttributesNew = 'checked="checked"';
992 $llRemark1 = 'Enter a name for your TYPO3 database.';
993 } elseif (is_array($createDatabaseAllowed)) {
994 $llRemark1 = 'Enter a name for your TYPO3 database.';
995 $llDbPatternRemark = 'The name has to match one of these names/patterns (% is a wild card):';
996 $llDbPatternList = '<li>' . implode('</li><li>', $createDatabaseAllowed) . '</li>';
997 $usePatternList = TRUE;
998 } else {
999 $formFieldAttributesNew = 'disabled="disabled"';
1000 $formFieldAttributesSelect = 'checked="checked"';
1001 $llRemark1 = 'You have no permissions to create new databases.';
1002 }
1003 // Substitute the subpart for the database options
1004 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($step3SubPart, '###DATABASEOPTIONS###', implode(LF, $step3DatabaseOptions));
1005 if ($usePatternList === FALSE) {
1006 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($content, '###DATABASE_NAME_PATTERNS###', '');
1007 }
1008 // Define the markers content
1009 $step3SubPartMarkers = array(
1010 'step' => $this->step + 1,
1011 'llOptions' => 'You have two options:',
1012 'action' => htmlspecialchars($this->action),
1013 'llOption1' => 'Create a new database (recommended):',
1014 'llRemark1' => $llRemark1,
1015 'll_Db_Pattern_Remark' => $llDbPatternRemark,
1016 'll_Db_Pattern_List' => $llDbPatternList,
1017 'formFieldAttributesNew' => $formFieldAttributesNew,
1018 'formFieldAttributesSelect' => $formFieldAttributesSelect,
1019 'llOption2' => 'Select an EMPTY existing database:',
1020 'llRemark2' => 'Any tables used by TYPO3 will be overwritten.',
1021 'continue' => 'Continue'
1022 );
1023 // Add step marker for main template
1024 $markers['step'] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($content, $step3SubPartMarkers, '###|###', TRUE, TRUE);
1025 } else {
1026 // Add step marker for main template when no connection
1027 $markers['step'] = $error_missingConnect;
1028 }
1029 break;
1030 case 4:
1031 // Add header marker for main template
1032 $markers['header'] = 'Import the Database Tables';
1033 // There should be a database host connection at this point
1034 if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
1035 // The selected database should be accessible
1036 if ($GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
1037 // Get the subpart for the fourth step
1038 $step4SubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEP4###');
1039 // Get the subpart for the database type options
1040 $step4DatabaseTypeOptionsSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($step4SubPart, '###DATABASETYPEOPTIONS###');
1041 $sFiles = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir(PATH_typo3conf, 'sql', 1, 1);
1042 // Check if default database scheme "database.sql" already exists, otherwise create it
1043 if (!strstr((implode(',', $sFiles) . ','), '/database.sql,')) {
1044 array_unshift($sFiles, 'Default TYPO3 Tables');
1045 }
1046 $step4DatabaseTypeOptions = array();
1047 foreach ($sFiles as $f) {
1048 if ($f == 'Default TYPO3 Tables') {
1049 $key = 'CURRENT_TABLES+STATIC';
1050 } else {
1051 $key = htmlspecialchars($f);
1052 }
1053 // Define the markers content for database type subpart
1054 $step4DatabaseTypeOptionMarkers = array(
1055 'databaseTypeValue' => 'import|' . $key,
1056 'databaseName' => htmlspecialchars(basename($f))
1057 );
1058 // Add the option HTML to an array
1059 $step4DatabaseTypeOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($step4DatabaseTypeOptionsSubPart, $step4DatabaseTypeOptionMarkers, '###|###', TRUE, FALSE);
1060 }
1061 // Substitute the subpart for the database type options
1062 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($step4SubPart, '###DATABASETYPEOPTIONS###', implode(LF, $step4DatabaseTypeOptions));
1063 // Define the markers content
1064 $step4SubPartMarkers = array(
1065 'llSummary' => 'Database summary:',
1066 'llUsername' => 'Username:',
1067 'username' => htmlspecialchars(TYPO3_db_username),
1068 'llHost' => 'Host:',
1069 'host' => htmlspecialchars(TYPO3_db_host),
1070 'llDatabase' => 'Database:',
1071 'database' => htmlspecialchars(TYPO3_db),
1072 'llNumberTables' => 'Number of tables:',
1073 'numberTables' => count($whichTables),
1074 'action' => htmlspecialchars($this->action),
1075 'llDatabaseType' => 'Select database contents:',
1076 'label' => 'Import database'
1077 );
1078 // Add step marker for main template
1079 $markers['step'] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($content, $step4SubPartMarkers, '###|###', TRUE, TRUE);
1080 } else {
1081 // Add step marker for main template when no database
1082 $markers['step'] = $error_missingDB;
1083 }
1084 } else {
1085 // Add step marker for main template when no connection
1086 $markers['step'] = $error_missingConnect;
1087 }
1088 break;
1089 case 'go':
1090 // Add header marker for main template
1091 $markers['header'] = 'Congratulations!';
1092 // There should be a database host connection at this point
1093 if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
1094 // The selected database should be accessible
1095 if ($GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
1096 // The database should contain tables
1097 if (count($whichTables)) {
1098 // Get the subpart for the go step
1099 $stepGoSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###STEPGO###');
1100 // Define the markers content
1101 $stepGoSubPartMarkers = array(
1102 'messageBasicFinished' => $this->messageBasicFinished(),
1103 'llImportant' => 'Important Security Warning',
1104 'securityRisk' => $this->securityRisk(),
1105 'llSwitchMode' => '
1106 <a href="' . $this->scriptSelf . '">
1107 Change the Install Tool password here
1108 </a>
1109 '
1110 );
1111 // Add step marker for main template
1112 $markers['step'] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($stepGoSubPart, $stepGoSubPartMarkers, '###|###', TRUE, TRUE);
1113 } else {
1114 // Add step marker for main template when empty database
1115 $markers['step'] = $error_emptyDB;
1116 }
1117 } else {
1118 // Add step marker for main template when no database
1119 $markers['step'] = $error_missingDB;
1120 }
1121 } else {
1122 // Add step marker for main template when no connection
1123 $markers['step'] = $error_missingConnect;
1124 }
1125 break;
1126 }
1127 }
1128 // Fill the markers in the template
1129 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markers, '###|###', TRUE, FALSE);
1130 return $content;
1131 }
1132
1133 /**
1134 * Calling the functions that checks the system
1135 *
1136 * @return void
1137 * @todo Define visibility
1138 */
1139 public function checkTheConfig() {
1140 // Order important:
1141 $this->checkDirs();
1142 $this->checkConfiguration();
1143 $this->checkExtensions();
1144 if (TYPO3_OS == 'WIN') {
1145 $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\\');
1146 if (!isset($_SERVER['PATH'])) {
1147 $serverPath = array_change_key_case($_SERVER, CASE_UPPER);
1148 $paths = array_merge($paths, explode(';', $serverPath['PATH']));
1149 } else {
1150 $paths = array_merge($paths, explode(';', $_SERVER['PATH']));
1151 }
1152 } else {
1153 $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/');
1154 $paths = array_merge($paths, explode(':', $_SERVER['PATH']));
1155 }
1156 $paths = array_unique($paths);
1157 asort($paths);
1158 if (\TYPO3\CMS\Core\Utility\PhpOptionsUtility::isSafeModeEnabled()) {
1159 $paths = array(ini_get('safe_mode_exec_dir'), '/usr/local/php/bin/');
1160 }
1161 if ($this->INSTALL['checkIM']['lzw']) {
1162 $this->checkIMlzw = 1;
1163 }
1164 if ($this->INSTALL['checkIM']['path']) {
1165 $paths[] = trim($this->INSTALL['checkIM']['path']);
1166 }
1167 if ($this->checkIM) {
1168 $this->checkImageMagick($paths);
1169 }
1170 $this->checkDatabase();
1171 }
1172
1173 /**
1174 * Editing files in typo3conf directory (or elsewhere if enabled)
1175 *
1176 * @return void
1177 * @todo Define visibility
1178 */
1179 public function typo3conf_edit() {
1180 // default:
1181 $EDIT_path = PATH_typo3conf;
1182 if ($this->allowFileEditOutsite_typo3conf_dir && $this->INSTALL['FILE']['EDIT_path']) {
1183 if (\TYPO3\CMS\Core\Utility\GeneralUtility::validPathStr($this->INSTALL['FILE']['EDIT_path']) && substr($this->INSTALL['FILE']['EDIT_path'], -1) == '/') {
1184 $tmp_path = PATH_site . $this->INSTALL['FILE']['EDIT_path'];
1185 if (is_dir($tmp_path)) {
1186 $EDIT_path = $tmp_path;
1187 } else {
1188 $this->errorMessages[] = '
1189 \'' . $tmp_path . '\' was not directory
1190 ';
1191 }
1192 } else {
1193 $this->errorMessages[] = '
1194 Bad directory name (must be like t3lib/ or media/script/)
1195 ';
1196 }
1197 }
1198 $headCode = 'Edit files in ' . basename($EDIT_path) . '/';
1199 $messages = '';
1200 if ($this->INSTALL['SAVE_FILE']) {
1201 $save_to_file = $this->INSTALL['FILE']['name'];
1202 if (@is_file($save_to_file)) {
1203 $save_to_file_md5 = md5($save_to_file);
1204 if (isset($this->INSTALL['FILE'][$save_to_file_md5]) && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($save_to_file, $EDIT_path . '') && substr($save_to_file, -1) != '~' && !strstr($save_to_file, '_bak')) {
1205 $this->INSTALL['typo3conf_files'] = $save_to_file;
1206 $save_fileContent = $this->INSTALL['FILE'][$save_to_file_md5];
1207 if ($this->INSTALL['FILE']['win_to_unix_br']) {
1208 $save_fileContent = str_replace(CRLF, LF, $save_fileContent);
1209 }
1210 $backupFile = $this->getBackupFilename($save_to_file);
1211 if ($this->INSTALL['FILE']['backup']) {
1212 if (@is_file($backupFile)) {
1213 unlink($backupFile);
1214 }
1215 rename($save_to_file, $backupFile);
1216 $messages .= '
1217 Backup written to <strong>' . $backupFile . '</strong>
1218 <br />
1219 ';
1220 }
1221 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($save_to_file, $save_fileContent);
1222 $messages .= '
1223 File saved: <strong>' . $save_to_file . '</strong>
1224 <br />
1225 MD5-sum: ' . $this->INSTALL['FILE']['prevMD5'] . ' (prev)
1226 <br />
1227 MD5-sum: ' . md5($save_fileContent) . ' (new)
1228 <br />
1229 ';
1230 }
1231 }
1232 }
1233 // Filelist:
1234 // Get the template file
1235 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'Typo3ConfEdit.html'));
1236 // Get the template part from the file
1237 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
1238 // Get the subpart for the files
1239 $filesSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###FILES###');
1240 $files = array();
1241 $typo3conf_files = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir($EDIT_path, '', 1, 1);
1242 $fileFound = 0;
1243 foreach ($typo3conf_files as $k => $file) {
1244 // Delete temp_CACHED files if option is set
1245 if ($this->INSTALL['delTempCached'] && preg_match('|/temp_CACHED_[a-z0-9_]+\\.php|', $file)) {
1246 unlink($file);
1247 continue;
1248 }
1249 if ($this->INSTALL['typo3conf_files'] && !strcmp($this->INSTALL['typo3conf_files'], $file)) {
1250 $fileFound = 1;
1251 }
1252 // Define the markers content for the files subpart
1253 $filesMarkers = array(
1254 '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',
1255 'fileName' => basename($file),
1256 'fileSize' => \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize(filesize($file)),
1257 'class' => $this->INSTALL['typo3conf_files'] && !strcmp($this->INSTALL['typo3conf_files'], $file) ? 'class="act"' : ''
1258 );
1259 // Fill the markers in the subpart
1260 $files[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($filesSubpart, $filesMarkers, '###|###', TRUE, FALSE);
1261 }
1262 if ($fileFound && @is_file($this->INSTALL['typo3conf_files'])) {
1263 $backupFile = $this->getBackupFilename($this->INSTALL['typo3conf_files']);
1264 $fileContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($this->INSTALL['typo3conf_files']);
1265 // Get the subpart to edit the files
1266 $fileEditTemplate = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###FILEEDIT###');
1267 $allowFileEditOutsideTypo3ConfDirSubPart = '';
1268 if (substr($this->INSTALL['typo3conf_files'], -1) != '~' && !strstr($this->INSTALL['typo3conf_files'], '_bak')) {
1269 // Get the subpart to show the save button
1270 $showSaveButtonSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($fileEditTemplate, '###SHOWSAVEBUTTON###');
1271 }
1272 if ($this->allowFileEditOutsite_typo3conf_dir) {
1273 // Get the subpart to show if files are allowed outside the directory typo3conf
1274 $allowFileEditOutsideTypo3ConfDirSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($fileEditTemplate, '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###');
1275 }
1276 // Substitute the subpart for the save button
1277 $fileEditContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($fileEditTemplate, '###SHOWSAVEBUTTON###', $showSaveButtonSubPart);
1278 // Substitute the subpart to show if files are allowed outside the directory typo3conf
1279 $fileEditContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($fileEditContent, '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###', $allowFileEditOutsideTypo3ConfDirSubPart);
1280 // Define the markers content for subpart to edit the files
1281 $fileEditMarkers = array(
1282 'messages' => !empty($messages) ? '<p class="typo3-message message-warning">' . $messages . '</p>' : '',
1283 'action' => $this->action . '#fileEditHeader',
1284 'saveFile' => 'Save file',
1285 'close' => 'Close',
1286 'llEditing' => 'Editing file:',
1287 'file' => $this->INSTALL['typo3conf_files'],
1288 'md5Sum' => 'MD5-sum: ' . md5($fileContent),
1289 'fileName' => $this->INSTALL['typo3conf_files'],
1290 'fileEditPath' => $this->INSTALL['FILE']['EDIT_path'],
1291 'filePreviousMd5' => md5($fileContent),
1292 'fileMd5' => md5($this->INSTALL['typo3conf_files']),
1293 'fileContent' => \TYPO3\CMS\Core\Utility\GeneralUtility::formatForTextarea($fileContent),
1294 'winToUnixBrChecked' => TYPO3_OS == 'WIN' ? '' : 'checked="checked"',
1295 'winToUnixBr' => 'Convert Windows linebreaks (13-10) to Unix (10)',
1296 'backupChecked' => @is_file($backupFile) ? 'checked="checked"' : '',
1297 'backup' => 'Make backup copy (rename to ' . basename($backupFile) . ')'
1298 );
1299 // Fill the markers in the subpart to edit the files
1300 $fileEditContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($fileEditContent, $fileEditMarkers, '###|###', TRUE, FALSE);
1301 }
1302 if ($this->allowFileEditOutsite_typo3conf_dir) {
1303 // Get the subpart to show if files are allowed outside the directory typo3conf
1304 $allowFileEditOutsideTypo3ConfDirSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###');
1305 // Define the markers content
1306 $allowFileEditOutsideTypo3ConfDirMarkers = array(
1307 'action' => $this->action,
1308 'pathSite' => PATH_site,
1309 'editPath' => $this->INSTALL['FILE']['EDIT_path'],
1310 'set' => 'Set'
1311 );
1312 // Fill the markers in the subpart
1313 $allowFileEditOutsideTypo3ConfDirSubPart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($allowFileEditOutsideTypo3ConfDirSubPart, $allowFileEditOutsideTypo3ConfDirMarkers, '###|###', TRUE, FALSE);
1314 }
1315 // Substitute the subpart to edit the file
1316 $fileListContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###FILEEDIT###', $fileEditContent);
1317 // Substitute the subpart when files can be edited outside typo3conf directory
1318 $fileListContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($fileListContent, '###ALLOWFILEEDITOUTSIDETYPO3CONFDIR###', $allowFileEditOutsideTypo3ConfDirSubPart);
1319 // Substitute the subpart for the files
1320 $fileListContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($fileListContent, '###FILES###', implode(LF, $files));
1321 // Define the markers content
1322 $fileListMarkers = array(
1323 'editPath' => '(' . $EDIT_path . ')',
1324 'deleteTempCachedUrl' => $this->action . '&amp;TYPO3_INSTALL[delTempCached]=1',
1325 'deleteTempCached' => 'Delete temp_CACHED* files'
1326 );
1327 // Fill the markers
1328 $fileListContent = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($fileListContent, $fileListMarkers, '###|###', TRUE, FALSE);
1329 // Add the content to the message array
1330 $this->message($headCode, 'Files in folder', $fileListContent);
1331 // Output the page
1332 $this->output($this->outputWrapper($this->printAll()));
1333 }
1334
1335 /**
1336 * Outputs system information
1337 *
1338 * @return void
1339 * @todo Define visibility
1340 */
1341 public function phpinformation() {
1342 $headCode = 'PHP information';
1343 $sVar = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('_ARRAY');
1344 $sVar['CONST: PHP_OS'] = PHP_OS;
1345 $sVar['CONST: TYPO3_OS'] = TYPO3_OS;
1346 $sVar['CONST: PATH_thisScript'] = PATH_thisScript;
1347 $sVar['CONST: php_sapi_name()'] = PHP_SAPI;
1348 $sVar['OTHER: TYPO3_VERSION'] = TYPO3_version;
1349 $sVar['OTHER: PHP_VERSION'] = phpversion();
1350 $sVar['imagecreatefromgif()'] = function_exists('imagecreatefromgif');
1351 $sVar['imagecreatefrompng()'] = function_exists('imagecreatefrompng');
1352 $sVar['imagecreatefromjpeg()'] = function_exists('imagecreatefromjpeg');
1353 $sVar['imagegif()'] = function_exists('imagegif');
1354 $sVar['imagepng()'] = function_exists('imagepng');
1355 $sVar['imagejpeg()'] = function_exists('imagejpeg');
1356 $sVar['imagettftext()'] = function_exists('imagettftext');
1357 $sVar['OTHER: IMAGE_TYPES'] = function_exists('imagetypes') ? imagetypes() : 0;
1358 $sVar['OTHER: memory_limit'] = ini_get('memory_limit');
1359 $gE_keys = explode(',', 'SERVER_PORT,SERVER_SOFTWARE,GATEWAY_INTERFACE,SCRIPT_NAME,PATH_TRANSLATED');
1360 foreach ($gE_keys as $k) {
1361 $sVar['SERVER: ' . $k] = $_SERVER[$k];
1362 }
1363 $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');
1364 foreach ($gE_keys as $k) {
1365 $sVar['T3CV_GFX: ' . $k] = $GLOBALS['TYPO3_CONF_VARS']['GFX'][$k];
1366 }
1367 $debugInfo = array(
1368 '### DEBUG SYSTEM INFORMATION - START ###'
1369 );
1370 foreach ($sVar as $kkk => $vvv) {
1371 $debugInfo[] = str_pad(substr($kkk, 0, 20), 20) . ': ' . $vvv;
1372 }
1373 $debugInfo[] = '### DEBUG SYSTEM INFORMATION - END ###';
1374 // Get the template file
1375 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'PhpInformation.html'));
1376 // Get the template part from the file
1377 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
1378 // Define the markers content
1379 $markers = array(
1380 '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!',
1381 'debugInfo' => \TYPO3\CMS\Core\Utility\GeneralUtility::formatForTextarea(implode(LF, $debugInfo))
1382 );
1383 // Fill the markers
1384 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markers, '###|###', TRUE, FALSE);
1385 // Add the content to the message array
1386 $this->message($headCode, 'DEBUG information', $content);
1387 // Start with various server information
1388 $getEnvArray = array();
1389 $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');
1390 foreach ($gE_keys as $k) {
1391 $getEnvArray[$k] = getenv($k);
1392 }
1393 $this->message($headCode, 'TYPO3\\CMS\\Core\\Utility\\GeneralUtility::getIndpEnv()', $this->viewArray(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('_ARRAY')));
1394 $this->message($headCode, 'getenv()', $this->viewArray($getEnvArray));
1395 $this->message($headCode, '_ENV', $this->viewArray($_ENV));
1396 $this->message($headCode, '_SERVER', $this->viewArray($_SERVER));
1397 $this->message($headCode, '_COOKIE', $this->viewArray($_COOKIE));
1398 $this->message($headCode, '_GET', $this->viewArray($_GET));
1399 // Start with the phpinfo() part
1400 ob_start();
1401 phpinfo();
1402 $contents = explode('<body>', ob_get_contents());
1403 ob_end_clean();
1404 $contents = explode('</body>', $contents[1]);
1405 // Do code cleaning: phpinfo() is not XHTML1.1 compliant
1406 $phpinfo = str_replace('<font', '<span', $contents[0]);
1407 $phpinfo = str_replace('</font', '</span', $phpinfo);
1408 $phpinfo = str_replace('<img border="0"', '<img', $phpinfo);
1409 $phpinfo = str_replace('<a name=', '<a id=', $phpinfo);
1410 // Add phpinfo() to the message array
1411 $this->message($headCode, 'phpinfo()', '
1412 <div class="phpinfo">
1413 ' . $phpinfo . '
1414 </div>
1415 ');
1416 // Output the page
1417 $this->output($this->outputWrapper($this->printAll()));
1418 }
1419
1420 /*******************************
1421 *
1422 * cleanup manager
1423 *
1424 *******************************/
1425 /**
1426 * Provides a tool cleaning up various tables in the database
1427 *
1428 * @return void
1429 * @author Robert Lemke <rl@robertlemke.de>
1430 * @todo Add more functionality ...
1431 * @todo Define visibility
1432 */
1433 public function cleanupManager() {
1434 $headCode = 'Clean up your TYPO3 installation';
1435 $this->message($headCode, 'Database cache tables', '
1436 <p>
1437 <strong>Clear cached image sizes</strong>
1438 <br />
1439 Clears the cache used for memorizing sizes of all images used in
1440 your website. This information is cached in order to gain
1441 performance and will be stored each time a new image is being
1442 displayed in the frontend.
1443 </p>
1444 <p>
1445 You should <em>Clear All Cache</em> in the backend after
1446 clearing this cache.
1447 </p>
1448 ');
1449 $tables = $this->sqlHandler->getListOfTables();
1450 $action = $this->INSTALL['cleanup_type'];
1451 if (($action == 'cache_imagesizes' || $action == 'all') && isset($tables['cache_imagesizes'])) {
1452 $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cache_imagesizes');
1453 }
1454 $cleanupType = array(
1455 'all' => 'Clean up everything'
1456 );
1457 // Get cache_imagesizes info
1458 if (isset($tables['cache_imagesizes'])) {
1459 $cleanupType['cache_imagesizes'] = 'Clear cached image sizes only';
1460 $cachedImageSizesCounter = intval($GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cache_imagesizes'));
1461 } else {
1462 $this->message($headCode, 'Table cache_imagesizes does not exist!', '
1463 <p>
1464 The table cache_imagesizes was not found. Please check your
1465 database settings in Basic Configuration and compare your
1466 table definition with the Database Analyzer.
1467 </p>
1468 ', 2);
1469 $cachedImageSizesCounter = 'unknown';
1470 }
1471 // Get the template file
1472 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'CleanUpManager.html'));
1473 // Get the template part from the file
1474 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
1475 // Get the subpart for the 'Clean up' dropdown
1476 $cleanUpOptionsSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###CLEANUPOPTIONS###');
1477 $cleanUpOptions = array();
1478 foreach ($cleanupType as $cleanUpKey => $cleanUpValue) {
1479 // Define the markers content
1480 $cleanUpMarkers = array(
1481 'value' => htmlspecialchars($cleanUpKey),
1482 'data' => htmlspecialchars($cleanUpValue)
1483 );
1484 // Fill the markers in the subpart
1485 $cleanUpOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($cleanUpOptionsSubpart, $cleanUpMarkers, '###|###', TRUE, FALSE);
1486 }
1487 // Substitute the subpart for the 'Clean up' dropdown
1488 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###CLEANUPOPTIONS###', implode(LF, $cleanUpOptions));
1489 // Define the markers content
1490 $markers = array(
1491 'numberCached' => 'Number cached image sizes:',
1492 'number' => $cachedImageSizesCounter,
1493 'action' => $this->action,
1494 'cleanUp' => 'Clean up',
1495 'execute' => 'Execute'
1496 );
1497 // Fill the markers
1498 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($content, $markers, '###|###', TRUE, FALSE);
1499 // Add the content to the message array
1500 $this->message($headCode, 'Statistics', $content, 1);
1501 $this->message($headCode, 'typo3temp/ folder', '
1502 <p>
1503 TYPO3 uses this directory for temporary files, mainly processed
1504 and cached images.
1505 <br />
1506 The filenames are very cryptic; They are unique representations
1507 of the file properties made by md5-hashing a serialized array
1508 with information.
1509 <br />
1510 Anyway this directory may contain many thousand files and a lot
1511 of them may be of no use anymore.
1512 </p>
1513 <p>
1514 With this test you can delete the files in this folder. When you
1515 do that, you should also clear the cache database tables
1516 afterwards.
1517 </p>
1518 ');
1519 if (!$this->config_array['dir_typo3temp']) {
1520 $this->message('typo3temp/ directory', 'typo3temp/ not writable!', '
1521 <p>
1522 You must make typo3temp/ write enabled before you can
1523 proceed with this test.
1524 </p>
1525 ', 2);
1526 $this->output($this->outputWrapper($this->printAll()));
1527 return;
1528 }
1529 // Run through files
1530 $fileCounter = 0;
1531 $deleteCounter = 0;
1532 $criteriaMatch = 0;
1533 $tmap = array('day' => 1, 'week' => 7, 'month' => 30);
1534 $tt = $this->INSTALL['typo3temp_delete'];
1535 $subdir = $this->INSTALL['typo3temp_subdir'];
1536 if (strlen($subdir) && !preg_match('/^[[:alnum:]_]+\\/$/', $subdir)) {
1537 die('subdir "' . $subdir . '" was not allowed!');
1538 }
1539 $action = $this->INSTALL['typo3temp_action'];
1540 $d = @dir(($this->typo3temp_path . $subdir));
1541 if (is_object($d)) {
1542 while ($entry = $d->read()) {
1543 $theFile = $this->typo3temp_path . $subdir . $entry;
1544 if (@is_file($theFile)) {
1545 $ok = 0;
1546 $fileCounter++;
1547 if ($tt) {
1548 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($tt)) {
1549 if (filesize($theFile) > $tt * 1024) {
1550 $ok = 1;
1551 }
1552 } else {
1553 if (fileatime($theFile) < $GLOBALS['EXEC_TIME'] - intval($tmap[$tt]) * 60 * 60 * 24) {
1554 $ok = 1;
1555 }
1556 }
1557 } else {
1558 $ok = 1;
1559 }
1560 if ($ok) {
1561 $hashPart = substr(basename($theFile), -14, 10);
1562 // This is a kind of check that the file being deleted has a 10 char hash in it
1563 if (!preg_match('/[^a-f0-9]/', $hashPart) || substr($theFile, -6) === '.cache' || substr($theFile, -4) === '.tbl' || substr(basename($theFile), 0, 8) === 'install_') {
1564 if ($action && $deleteCounter < $action) {
1565 $deleteCounter++;
1566 unlink($theFile);
1567 } else {
1568 $criteriaMatch++;
1569 }
1570 }
1571 }
1572 }
1573 }
1574 $d->close();
1575 }
1576 // Find sub-dirs:
1577 $subdirRegistry = array('' => '');
1578 $d = @dir($this->typo3temp_path);
1579 if (is_object($d)) {
1580 while ($entry = $d->read()) {
1581 $theFile = $entry;
1582 if (@is_dir(($this->typo3temp_path . $theFile)) && $theFile != '..' && $theFile != '.') {
1583 $subdirRegistry[$theFile . '/'] = $theFile . '/ (Files: ' . count(\TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir(($this->typo3temp_path . $theFile))) . ')';
1584 }
1585 }
1586 }
1587 $deleteType = array(
1588 '0' => 'All',
1589 'day' => 'Last access more than a day ago',
1590 'week' => 'Last access more than a week ago',
1591 'month' => 'Last access more than a month ago',
1592 '10' => 'Filesize greater than 10KB',
1593 '50' => 'Filesize greater than 50KB',
1594 '100' => 'Filesize greater than 100KB'
1595 );
1596 $actionType = array(
1597 '0' => 'Don\'t delete, just display statistics',
1598 '100' => 'Delete 100',
1599 '500' => 'Delete 500',
1600 '1000' => 'Delete 1000'
1601 );
1602 // Get the template file
1603 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'Typo3TempManager.html'));
1604 // Get the template part from the file
1605 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
1606 // Get the subpart for 'Delete files by condition' dropdown
1607 $deleteOptionsSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###DELETEOPTIONS###');
1608 $deleteOptions = array();
1609 foreach ($deleteType as $deleteKey => $deleteValue) {
1610 // Define the markers content
1611 $deleteMarkers = array(
1612 'value' => htmlspecialchars($deleteKey),
1613 'selected' => !strcmp($deleteKey, $tt) ? 'selected="selected"' : '',
1614 'data' => htmlspecialchars($deleteValue)
1615 );
1616 // Fill the markers in the subpart
1617 $deleteOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($deleteOptionsSubpart, $deleteMarkers, '###|###', TRUE, FALSE);
1618 }
1619 // Substitute the subpart for 'Delete files by condition' dropdown
1620 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###DELETEOPTIONS###', implode(LF, $deleteOptions));
1621 // Get the subpart for 'Number of files at a time' dropdown
1622 $actionOptionsSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###ACTIONOPTIONS###');
1623 $actionOptions = array();
1624 foreach ($actionType as $actionKey => $actionValue) {
1625 // Define the markers content
1626 $actionMarkers = array(
1627 'value' => htmlspecialchars($actionKey),
1628 'data' => htmlspecialchars($actionValue)
1629 );
1630 // Fill the markers in the subpart
1631 $actionOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($actionOptionsSubpart, $actionMarkers, '###|###', TRUE, FALSE);
1632 }
1633 // Substitute the subpart for 'Number of files at a time' dropdown
1634 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($content, '###ACTIONOPTIONS###', implode(LF, $actionOptions));
1635 // Get the subpart for 'From sub-directory' dropdown
1636 $subDirectoryOptionsSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###SUBDIRECTORYOPTIONS###');
1637 $subDirectoryOptions = array();
1638 foreach ($subdirRegistry as $subDirectoryKey => $subDirectoryValue) {
1639 // Define the markers content
1640 $subDirectoryMarkers = array(
1641 'value' => htmlspecialchars($subDirectoryKey),
1642 'selected' => !strcmp($subDirectoryKey, $this->INSTALL['typo3temp_subdir']) ? 'selected="selected"' : '',
1643 'data' => htmlspecialchars($subDirectoryValue)
1644 );
1645 // Fill the markers in the subpart
1646 $subDirectoryOptions[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($subDirectoryOptionsSubpart, $subDirectoryMarkers, '###|###', TRUE, FALSE);
1647 }
1648 // Substitute the subpart for 'From sub-directory' dropdown
1649 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($content, '###SUBDIRECTORYOPTIONS###', implode(LF, $subDirectoryOptions));
1650 // Define the markers content
1651 $markers = array(
1652 'numberTemporary' => 'Number of temporary files:',
1653 'numberMatching' => 'Number matching:',
1654 'numberDeleted' => 'Number deleted:',
1655 'temporary' => $fileCounter - $deleteCounter,
1656 'matching' => $criteriaMatch,
1657 'deleteType' => '<span>' . htmlspecialchars($deleteType[$tt]) . '</span>',
1658 'deleted' => $deleteCounter,
1659 'deleteCondition' => 'Delete files by condition',
1660 'numberFiles' => 'Number of files at a time:',
1661 'fromSubdirectory' => 'From sub-directory:',
1662 'execute' => 'Execute',
1663 'explanation' => '
1664 <p>
1665 This tool will delete files only if the last 10 characters
1666 before the extension (3 chars+\'.\') are hexadecimal valid
1667 ciphers, which are lowercase a-f and 0-9.
1668 </p>
1669 '
1670 );
1671 // Fill the markers
1672 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($content, $markers, '###|###', TRUE, FALSE);
1673 // Add the content to the message array
1674 $this->message($headCode, 'Statistics', $content, 1);
1675 // Output the page
1676 $this->output($this->outputWrapper($this->printAll()));
1677 }
1678
1679 /*******************************
1680 *
1681 * CONFIGURATION FORM
1682 *
1683 ********************************/
1684 /**
1685 * Creating the form for editing the TYPO3_CONF_VARS options.
1686 *
1687 * @param string $type If get_form, display form, otherwise checks and store in localconf.php
1688 * @return void
1689 * @todo Define visibility
1690 */
1691 public function generateConfigForm($type = '') {
1692 $default_config_content = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager')->getDefaultConfigurationFileResource());
1693 $commentArr = $this->getDefaultConfigArrayComments($default_config_content);
1694 switch ($type) {
1695 case 'get_form':
1696 // Get the template file
1697 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'GenerateConfigForm.html'));
1698 // Get the template part from the file
1699 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
1700 foreach ($GLOBALS['TYPO3_CONF_VARS'] as $k => $va) {
1701 $ext = '[' . $k . ']';
1702 $this->message($ext, '$TYPO3_CONF_VARS[\'' . $k . '\']', $commentArr[0][$k], 1);
1703 foreach ($va as $vk => $value) {
1704 if (isset($GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$k][$vk])) {
1705 // Don't allow editing stuff which is added by extensions
1706 // Make sure we fix potentially duplicated entries from older setups
1707 $potentialValue = str_replace(array('\'.chr(10).\'', '\' . LF . \''), array(LF, LF), $value);
1708 while (preg_match('/' . preg_quote($GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$k][$vk], '/') . '$/', '', $potentialValue)) {
1709 $potentialValue = preg_replace('/' . preg_quote($GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$k][$vk], '/') . '$/', '', $potentialValue);
1710 }
1711 $value = $potentialValue;
1712 }
1713 $textAreaSubpart = '';
1714 $booleanSubpart = '';
1715 $textLineSubpart = '';
1716 $description = trim($commentArr[1][$k][$vk]);
1717 $isTextarea = preg_match('/^(<.*?>)?string \\(textarea\\)/i', $description) ? TRUE : FALSE;
1718 $doNotRender = preg_match('/^(<.*?>)?string \\(exclude\\)/i', $description) ? TRUE : FALSE;
1719 if (!is_array($value) && !$doNotRender && (!preg_match('/[' . LF . CR . ']/', $value) || $isTextarea)) {
1720 $k2 = '[' . $vk . ']';
1721 if ($isTextarea) {
1722 // Get the subpart for a textarea
1723 $textAreaSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###TEXTAREA###');
1724 // Define the markers content
1725 $textAreaMarkers = array(
1726 'id' => $k . '-' . $vk,
1727 'name' => 'TYPO3_INSTALL[extConfig][' . $k . '][' . $vk . ']',
1728 'value' => htmlspecialchars(str_replace(array('\'.chr(10).\'', '\' . LF . \''), array(LF, LF), $value))
1729 );
1730 // Fill the markers in the subpart
1731 $textAreaSubpart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($textAreaSubpart, $textAreaMarkers, '###|###', TRUE, FALSE);
1732 } elseif (preg_match('/^(<.*?>)?boolean/i', $description)) {
1733 // Get the subpart for a checkbox
1734 $booleanSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###BOOLEAN###');
1735 // Define the markers content
1736 $booleanMarkers = array(
1737 'id' => $k . '-' . $vk,
1738 'name' => 'TYPO3_INSTALL[extConfig][' . $k . '][' . $vk . ']',
1739 'value' => $value && strcmp($value, '0') ? $value : 1,
1740 'checked' => $value ? 'checked="checked"' : ''
1741 );
1742 // Fill the markers in the subpart
1743 $booleanSubpart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($booleanSubpart, $booleanMarkers, '###|###', TRUE, FALSE);
1744 } else {
1745 // Get the subpart for an input text field
1746 $textLineSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###TEXTLINE###');
1747 // Define the markers content
1748 $textLineMarkers = array(
1749 'id' => $k . '-' . $vk,
1750 'name' => 'TYPO3_INSTALL[extConfig][' . $k . '][' . $vk . ']',
1751 'value' => htmlspecialchars($value)
1752 );
1753 // Fill the markers in the subpart
1754 $textLineSubpart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($textLineSubpart, $textLineMarkers, '###|###', TRUE, FALSE);
1755 }
1756 // Substitute the subpart for a textarea
1757 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###TEXTAREA###', $textAreaSubpart);
1758 // Substitute the subpart for a checkbox
1759 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($content, '###BOOLEAN###', $booleanSubpart);
1760 // Substitute the subpart for an input text field
1761 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($content, '###TEXTLINE###', $textLineSubpart);
1762 // Define the markers content
1763 $markers = array(
1764 'description' => $description,
1765 'key' => '[' . $k . '][' . $vk . ']',
1766 'label' => htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($value, 40))
1767 );
1768 // Fill the markers
1769 $content = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($content, $markers, '###|###', TRUE, FALSE);
1770 // Add the content to the message array
1771 $this->message($ext, $k2, $content);
1772 }
1773 }
1774 }
1775 break;
1776 default:
1777 if (is_array($this->INSTALL['extConfig'])) {
1778 $configurationPathValuePairs = array();
1779 foreach ($this->INSTALL['extConfig'] as $k => $va) {
1780 if (is_array($GLOBALS['TYPO3_CONF_VARS'][$k])) {
1781 foreach ($va as $vk => $value) {
1782 if (isset($GLOBALS['TYPO3_CONF_VARS'][$k][$vk])) {
1783 $doit = 1;
1784 if ($k == 'BE' && $vk == 'installToolPassword') {
1785 if ($value) {
1786 if (isset($_POST['installToolPassword_check'])) {
1787 if (!$this->formProtection->validateToken((string) $_POST['formToken'], 'installToolPassword', 'change')) {
1788 $doit = FALSE;
1789 break;
1790 }
1791 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('installToolPassword_check') || strcmp(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('installToolPassword_check'), $value)) {
1792 $doit = FALSE;
1793 $this->errorMessages[] = 'The two passwords did not ' . 'match! The password was not changed.';
1794 }
1795 }
1796 if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('installToolPassword_md5')) {
1797 $value = md5($value);
1798 }
1799 } else {
1800 $doit = 0;
1801 }
1802 }
1803 $description = trim($commentArr[1][$k][$vk]);
1804 if (preg_match('/^string \\(textarea\\)/i', $description)) {
1805 // Force Unix linebreaks in textareas
1806 $value = str_replace(CR, '', $value);
1807 // Preserve linebreaks
1808 $value = str_replace(LF, '\' . LF . \'', $value);
1809 }
1810 if (preg_match('/^boolean/i', $description)) {
1811 // When submitting settings in the Install Tool, values that default to "FALSE" or "TRUE"
1812 // in EXT:core/Configuration/DefaultConfiguration.php will be sent as "0" resp. "1".
1813 // Therefore, reset the values to their boolean equivalent.
1814 if ($GLOBALS['TYPO3_CONF_VARS'][$k][$vk] === FALSE && $value === '0') {
1815 $value = FALSE;
1816 } elseif ($GLOBALS['TYPO3_CONF_VARS'][$k][$vk] === TRUE && $value === '1') {
1817 $value = TRUE;
1818 }
1819 }
1820 if ($doit && strcmp($GLOBALS['TYPO3_CONF_VARS'][$k][$vk], $value)) {
1821 $configurationPathValuePairs['"' . $k . '"' . '/' . '"' . $vk . '"'] = $value;
1822 }
1823 }
1824 }
1825 }
1826 }
1827 $this->setLocalConfigurationValues($configurationPathValuePairs);
1828 }
1829 break;
1830 }
1831 }
1832
1833 /**
1834 * Make an array of the comments in the EXT:core/Configuration/DefaultConfiguration.php file
1835 *
1836 * @param string $string The contents of the EXT:core/Configuration/DefaultConfiguration.php file
1837 * @param array $mainArray
1838 * @param array $commentArray
1839 * @return array
1840 * @todo Define visibility
1841 */
1842 public function getDefaultConfigArrayComments($string, $mainArray = array(), $commentArray = array()) {
1843 $lines = explode(LF, $string);
1844 $in = 0;
1845 $mainKey = '';
1846 foreach ($lines as $lc) {
1847 $lc = trim($lc);
1848 if ($in) {
1849 if (!strcmp($lc, ');')) {
1850 $in = 0;
1851 } else {
1852 if (preg_match('/["\']([[:alnum:]_-]*)["\'][[:space:]]*=>(.*)/i', $lc, $reg)) {
1853 preg_match('/,[\\t\\s]*\\/\\/(.*)/i', $reg[2], $creg);
1854 $theComment = trim($creg[1]);
1855 if (substr(strtolower(trim($reg[2])), 0, 5) == 'array' && !strcmp($reg[1], strtoupper($reg[1]))) {
1856 $mainKey = trim($reg[1]);
1857 $mainArray[$mainKey] = $theComment;
1858 } elseif ($mainKey) {
1859 $commentArray[$mainKey][$reg[1]] = $theComment;
1860 }
1861 }
1862 }
1863 }
1864 if (!strcmp($lc, 'return array(')) {
1865 $in = 1;
1866 }
1867 }
1868 return array($mainArray, $commentArray);
1869 }
1870
1871 /*******************************
1872 *
1873 * CHECK CONFIGURATION FUNCTIONS
1874 *
1875 *******************************/
1876 /**
1877 * Checking php.ini configuration and set appropriate messages and flags.
1878 *
1879 * @return void
1880 * @todo Define visibility
1881 */
1882 public function checkConfiguration() {
1883 $ext = 'php.ini configuration checked';
1884 $this->message($ext);
1885 // *****************
1886 // Incoming values:
1887 // *****************
1888 // Includepath
1889 $incPaths = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(TYPO3_OS == 'WIN' ? ';' : ':', ini_get('include_path'));
1890 if (!in_array('.', $incPaths)) {
1891 $this->message($ext, 'Current directory (./) is not in include path!', '
1892 <p>
1893 <em>include_path=' . ini_get('include_path') . '</em>
1894 <br />
1895 Normally the current path, \'.\', is included in the
1896 include_path of PHP. Although TYPO3 does not rely on this,
1897 it is an unusual setting that may introduce problems for
1898 some extensions.
1899 </p>
1900 ', 1);
1901 } else {
1902 $this->message($ext, 'Current directory in include path', '', -1);
1903 }
1904 // *****************
1905 // File uploads
1906 // *****************
1907 if (!ini_get('file_uploads')) {
1908 $this->message($ext, 'File uploads not allowed', '
1909 <p>
1910 <em>file_uploads=' . ini_get('file_uploads') . '</em>
1911 <br />
1912 TYPO3 uses the ability to upload files from the browser in
1913 various cases.
1914 <br />
1915 As long as this flag is disabled, you\'ll not be able to
1916 upload files.
1917 <br />
1918 But it doesn\'t end here, because not only are files not
1919 accepted by the server - ALL content in the forms are
1920 discarded and therefore nothing at all will be editable
1921 if you don\'t set this flag!
1922 <br />
1923 However if you cannot enable fileupload for some reason
1924 alternatively you change the default form encoding value
1925 with \\$TYPO3_CONF_VARS[SYS][form_enctype].
1926 </p>
1927 ', 3);
1928 } else {
1929 $this->message($ext, 'File uploads allowed', '', -1);
1930 }
1931 $upload_max_filesize = \TYPO3\CMS\Core\Utility\GeneralUtility::getBytesFromSizeMeasurement(ini_get('upload_max_filesize'));
1932 $post_max_size = \TYPO3\CMS\Core\Utility\GeneralUtility::getBytesFromSizeMeasurement(ini_get('post_max_size'));
1933 if ($upload_max_filesize < 1024 * 1024 * 10) {
1934 $this->message($ext, 'Maximum upload filesize too small?', '
1935 <p>
1936 <em>upload_max_filesize=' . ini_get('upload_max_filesize') . '</em>
1937 <br />
1938 By default TYPO3 supports uploading, copying and moving
1939 files of sizes up to 10MB (You can alter the TYPO3 defaults
1940 by the config option TYPO3_CONF_VARS[BE][maxFileSize]).
1941 <br />
1942 Your current value is below this, so at this point, PHP sets
1943 the limits for uploaded filesizes and not TYPO3.
1944 <br />
1945 <strong>Notice:</strong> The limits for filesizes attached
1946 to database records are set in the tables.php configuration
1947 files (\\$TCA) for each group/file field. You may override
1948 these values in the local configuration or by page TSconfig settings.
1949 </p>
1950 ', 1);
1951 }
1952 if ($upload_max_filesize > $post_max_size) {
1953 $this->message($ext, 'Maximum size for POST requests is smaller than max. upload filesize', '
1954 <p>
1955 <em>upload_max_filesize=' . ini_get('upload_max_filesize') . '
1956 , post_max_size=' . ini_get('post_max_size') . '</em>
1957 <br />
1958 You have defined a maximum size for file uploads which
1959 exceeds the allowed size for POST requests. Therefore the
1960 file uploads can not be larger than ' . ini_get('post_max_size') . '
1961 </p>
1962 ', 1);
1963 }
1964 // *****************
1965 // Memory and functions
1966 // *****************
1967 $memory_limit_value = \TYPO3\CMS\Core\Utility\GeneralUtility::getBytesFromSizeMeasurement(ini_get('memory_limit'));
1968 if ($memory_limit_value <= 0) {
1969 $this->message($ext, 'Unlimited memory limit!', '<p>Your webserver is configured to not limit PHP memory usage at all. This is a risk
1970 and should be avoided in production setup. In general it\'s best practice to limit this
1971 in the configuration of your webserver. To be safe, ask the system administrator of the
1972 webserver to raise the limit to something over ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT . '.</p>', 2);
1973 } elseif ($memory_limit_value < \TYPO3\CMS\Core\Utility\GeneralUtility::getBytesFromSizeMeasurement(TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT)) {
1974 $this->message($ext, 'Memory limit below ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT, '
1975 <p>
1976 <em>memory_limit=' . ini_get('memory_limit') . '</em>
1977 <br />
1978 Your system is configured to enforce a memory limit of PHP
1979 scripts lower than ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT . '.
1980 The Extension Manager needs to include more PHP-classes than
1981 will fit into this memory space. There is nothing else to do
1982 than raise the limit. To be safe, ask the system
1983 administrator of the webserver to raise the limit to over
1984 ' . TYPO3_REQUIREMENTS_MINIMUM_PHP_MEMORY_LIMIT . '.
1985 </p>
1986 ', 3);
1987 } else {
1988 $this->message($ext, 'Memory limit: ' . ini_get('memory_limit'), '', -1);
1989 }
1990 if (ini_get('max_execution_time') < 30) {
1991 $this->message($ext, 'Maximum execution time below 30 seconds', '
1992 <p>
1993 <em>max_execution_time=' . ini_get('max_execution_time') . '</em>
1994 <br />
1995 May impose problems if too low.
1996 </p>
1997 ', 1);
1998 } else {
1999 $this->message($ext, 'Maximum execution time: ' . ini_get('max_execution_time') . ' seconds', '', -1);
2000 }
2001 if (ini_get('disable_functions')) {
2002 $this->message($ext, 'Functions disabled!', '
2003 <p>
2004 <em>disable_functions=' . ini_get('disable_functions') . '</em>
2005 <br />
2006 The above list of functions are disabled. If TYPO3 use any
2007 of these there might be trouble.
2008 <br />
2009 TYPO3 is designed to use the default set of PHP4.3.0+
2010 functions plus the functions of GDLib.
2011 <br />
2012 Possibly these functions are disabled due to security risks
2013 and most likely the list would include a function like
2014 <em>exec()</em> which is use by TYPO3 to access ImageMagick.
2015 </p>
2016 ', 2);
2017 } else {
2018 $this->message($ext, 'Functions disabled: none', '', -1);
2019 }
2020 // Mail tests
2021 if (TYPO3_OS == 'WIN') {
2022 $smtp = ini_get('SMTP');
2023 $bad_smtp = FALSE;
2024 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::validIP($smtp)) {
2025 $smtp_addr = @gethostbyname($smtp);
2026 $bad_smtp = $smtp_addr == $smtp;
2027 } else {
2028 $smtp_addr = $smtp;
2029 }
2030 if (!$smtp || $bad_smtp || !\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger(ini_get('smtp_port'))) {
2031 $this->message($ext, 'Mail configuration is not set correctly', '
2032 <p>
2033 Mail configuration is not set
2034 <br />
2035 PHP mail() function requires SMTP and smtp_port to have
2036 correct values on Windows.
2037 </p>
2038 ', 2);
2039 } else {
2040 if (($smtp_addr == '127.0.0.1' || $smtp_addr == '::1') && ($_SERVER['SERVER_ADDR'] == '127.0.0.1' || $_SERVER['SERVER_ADDR'] == '::1')) {
2041 $this->message($ext, 'Mail is configured (potential problem exists!)', '
2042 <p>
2043 <em>SMTP=' . $smtp . '</em> - <strong>Note:</strong>
2044 this server! Are you sure it runs SMTP server?
2045 <br />
2046 <em>smtp_port=' . ini_get('smtp_port') . '</em>
2047 </p>' . $this->check_mail('get_form') . '
2048 ', 1);
2049 } else {
2050 $this->message($ext, 'Mail is configured', '
2051 <p>
2052 <em>SMTP=' . $smtp . '</em>
2053 <br />
2054 <em>smtp_port=' . ini_get('smtp_port') . '</em>
2055 </p>' . $this->check_mail('get_form') . '
2056 ', -1);
2057 }
2058 }
2059 } elseif (!ini_get('sendmail_path')) {
2060 $this->message($ext, 'Sendmail path not defined!', '
2061 <p>
2062 This may be critical to TYPO3\'s use of the mail() function.
2063 Please be sure that the mail() function in your
2064 php-installation works!
2065 </p>' . $this->check_mail('get_form') . '
2066 ', 1);
2067 } else {
2068 list($prg) = explode(' ', ini_get('sendmail_path'));
2069 if (!@is_executable($prg)) {
2070 $this->message($ext, 'Sendmail program not found or not executable?', '
2071 <p>
2072 <em>sendmail_path=' . ini_get('sendmail_path') . '</em>
2073 <br />
2074 This may be critical to TYPO3\'s use of the mail()
2075 function. Please be sure that the mail() function in
2076 your php-installation works!
2077 </p>' . $this->check_mail('get_form') . '
2078 ', 1);
2079 } else {
2080 $this->message($ext, 'Sendmail OK', '
2081 <p>
2082 <em>sendmail_path=' . ini_get('sendmail_path') . '</em>
2083 </p>' . $this->check_mail('get_form') . '
2084 ', -1);
2085 }
2086 }
2087 // *****************
2088 // Safe mode related
2089 // *****************
2090 if (\TYPO3\CMS\Core\Utility\PhpOptionsUtility::isSafeModeEnabled()) {
2091 $this->message($ext, 'Safe mode turned on', '
2092 <p>
2093 <em>safe_mode=' . ini_get('safe_mode') . '</em>
2094 <br />
2095 In safe_mode PHP is restricted in several ways. This is a
2096 good thing because it adds protection to your (and others)
2097 scripts. But it may also introduce problems. In TYPO3 this
2098 <em>may be</em> a problem in two areas: File administration
2099 and execution of external programs, in particular
2100 ImageMagick.
2101 <br />
2102 If you just ignore this warning, you\'ll most likely find,
2103 that TYPO3 seems to work except from the image-generation.
2104 The problem in that case is that the external ImageMagick
2105 programs are not allowed to be executed from the regular
2106 paths like "/usr/bin/" or "/usr/X11R6/bin/".
2107 <br />
2108 If you use safe_mode with TYPO3, you should disable use of
2109 external programs ([BE][disable_exec_function]=1).
2110 <br />
2111 In safe mode you must ensure that all the php-scripts and
2112 upload folders are owned by the same user.
2113 </p>
2114 <p>
2115 <em>safe_mode_exec_dir=' . ini_get('safe_mode_exec_dir') . '</em>
2116 <br />
2117 If the ImageMagick utilities are located in this directory,
2118 everything is fine. Below on this page, you can see if
2119 ImageMagick is found here. If not, ask you ISP to put the
2120 three ImageMagick programs, \'convert\',
2121 \'combine\'/\'composite\' and \'identify\' there (eg. with
2122 symlinks if Unix server)
2123 </p>
2124 <p>
2125 <strong>Example of safe_mode settings:</strong>
2126 <br />
2127 Set this in the php.ini file:
2128 </p>
2129 <p>
2130 ; Safe Mode
2131 <br />
2132 safe_mode = On
2133 <br />
2134 safe_mode_exec_dir = /usr/bin/
2135 </p>
2136 <p>
2137 ...and the ImageMagick \'/usr/bin/convert\' will be
2138 executable.
2139 <br />
2140 The last slash is important (..../) and you can only specify
2141 one directory.
2142 </p>
2143 <p>
2144 <strong>Notice: </strong>
2145 <br />
2146 ImageMagick 6 or GraphicsMagick is recommended and the binaries are
2147 normally installed in /usr/bin.
2148 <br />
2149 Paths to ImageMagick are defined in local configuration and may be
2150 something else than /usr/bin/, but this is default for
2151 ImageMagick 6+
2152 </p>
2153 ', 2);
2154 if (ini_get('doc_root')) {
2155 $this->message($ext, 'doc_root set', '
2156 <p>
2157 <em>doc_root=' . ini_get('doc_root') . '</em>
2158 <br />
2159 PHP cannot execute scripts outside this directory. If
2160 that is a problem is please correct it.
2161 </p>
2162 ', 1);
2163 }
2164 $this->config_array['safemode'] = 1;
2165 } else {
2166 $this->message($ext, 'safe_mode: off', '', -1);
2167 }
2168 if (\TYPO3\CMS\Core\Utility\PhpOptionsUtility::isSqlSafeModeEnabled()) {
2169 $this->message($ext, 'sql.safe_mode is enabled', '
2170 <p>
2171 <em>sql.safe_mode=' . ini_get('sql.safe_mode') . '</em>
2172 <br />
2173 This means that you can only connect to the database with a
2174 username corresponding to the user of the webserver process
2175 or fileowner. Consult your ISP for information about this.
2176 Also see <a href="http://www.wrox.com/Consumer/Store/Books/2963/29632002.htm">
2177 http://www.wrox.com/Consumer/Store/Books/2963/29632002.htm</a>
2178 <br />
2179 The owner of the current file is:
2180 <strong>' . get_current_user() . '</strong>
2181 </p>
2182 ', 1);
2183 $this->config_array['sql.safe_mode_user'] = get_current_user();
2184 } else {
2185 $this->message($ext, 'sql.safe_mode: off', '', -1);
2186 }
2187 if (ini_get('open_basedir')) {
2188 $this->message($ext, 'open_basedir set', '
2189 <p>
2190 <em>open_basedir=' . ini_get('open_basedir') . '</em>
2191 <br />
2192 This restricts TYPO3 to open and include files only in this
2193 path. Please make sure that this does not prevent TYPO3 from
2194 running.
2195 <br />
2196 <strong>Notice (UNIX):</strong> Before checking a path
2197 according to open_basedir, PHP resolves all symbolic links.
2198 </p>
2199 ', 1);
2200 } else {
2201 $this->message($ext, 'open_basedir: off', '', -1);
2202 }
2203 // Check availability of PHP session support
2204 if (extension_loaded('session')) {
2205 $this->message($ext, 'PHP sessions available', '
2206 <p>
2207 <em>PHP Sessions available</em>
2208 <br />
2209 PHP is compiled with session support and session support is
2210 available.
2211 </p>
2212 ', -1);
2213 } else {
2214 $this->message($ext, 'PHP Sessions not available', '
2215 <p>
2216 PHP is not compiled with session support, or session support
2217 is disabled in php.ini.
2218 <br />
2219 TYPO3 needs session support.
2220 </p>
2221 ', 3);
2222 }
2223 // Suhosin/Hardened PHP:
2224 $suhosinDescription = '
2225 <p>
2226 Suhosin limits the number of elements that can be submitted in
2227 forms to the server. This will affect for example the
2228 "All configuration" section in the Install Tool or Inline
2229 Relational Record Editing (IRRE) with many child records.
2230 </p>';
2231 if (extension_loaded('suhosin')) {
2232 $suhosinSuggestion = '
2233 <p>
2234 At least a value of 400 is suggested.
2235 </p>
2236 ';
2237 $suhosinSuggestionGetMaxValueLength = '
2238 <p>
2239 At least a value of 2000 is suggested.
2240 </p>
2241 ';
2242 $suhosinRequestMaxVars = ini_get('suhosin.request.max_vars');
2243 $suhosinPostMaxVars = ini_get('suhosin.post.max_vars');
2244 $suhosinGetMaxValueLength = ini_get('suhosin.get.max_value_length');
2245 $suhosinRequestMaxVarsType = $suhosinRequestMaxVars < 400 ? 2 : -1;
2246 $suhosinPostMaxVarsType = $suhosinPostMaxVars < 400 ? 2 : -1;
2247 $suhosinGetMaxValueLengthType = $suhosinGetMaxValueLength < 2000 ? 2 : -1;
2248 $suhosinType = $suhosinRequestMaxVars < 400 || $suhosinPostMaxVars < 400 || $suhosinGetMaxValueLength < 2000 ? 2 : -1;
2249 $this->message($ext, 'Suhosin/Hardened PHP is loaded', $suhosinDescription, $suhosinType);
2250 $this->message($ext, 'suhosin.request.max_vars: ' . $suhosinRequestMaxVars, $suhosinSuggestion, $suhosinRequestMaxVarsType);
2251 $this->message($ext, 'suhosin.post.max_vars: ' . $suhosinPostMaxVars, $suhosinSuggestion, $suhosinPostMaxVarsType);
2252 $this->message($ext, 'suhosin.get.max_value_length: ' . $suhosinGetMaxValueLength, $suhosinSuggestionGetMaxValueLength, $suhosinGetMaxValueLengthType);
2253 } else {
2254 $this->message($ext, 'Suhosin/Hardened PHP is not loaded', $suhosinDescription, 0);
2255 }
2256 // Check for stripped PHPdoc comments that are required to evaluate annotations:
2257 $method = new \ReflectionMethod('TYPO3\\CMS\\Install\\Installer', 'check_mail');
2258 if (strlen($method->getDocComment()) === 0) {
2259 $description = '
2260 <p>
2261 The system extension Extbase evaluates annotations in PHPdoc
2262 comments and thus requires eAccelerator not to strip away
2263 these parts. However, this is currently the only part in the
2264 TYPO3 Core (beside deprecation log and unit tests). If
2265 Extbase is not used, recompiling eAccelerator is not
2266 required at all.
2267 <br/>
2268 <br/>
2269 If you do not want comments to be stripped by eAccelerator,
2270 please recompile with the following configuration setting
2271 (<a href="http://eaccelerator.net/ticket/229" target="_blank">
2272 more details</a>):
2273 <br />
2274 <em>--with-eaccelerator-doc-comment-inclusion</em>
2275 </p>
2276 ';
2277 $this->message($ext, 'PHPdoc comments are stripped', $description, 2);
2278 }
2279 // ThreadStackSize on Windows systems with Apache
2280 $threadStackSizeDescription = '
2281 <p>
2282 Fluid uses complex regular expressions which require a lot of stack space during the first processing.
2283 On Windows the default stack size for Apache is a lot smaller than on unix.
2284 You can increase the size to 8MB (default on unix) by adding to the httpd.conf:
2285 <br /><br />&lt;IfModule mpm_winnt_module&gt;
2286 <br />ThreadStackSize 8388608
2287 <br />&lt;/IfModule&gt;
2288 <br /><br />Restart Apache after this change.
2289 </p>';
2290 if (TYPO3_OS === 'WIN' && substr($_SERVER['SERVER_SOFTWARE'], 0, 6) === 'Apache') {
2291 $this->message($ext, 'ThreadStackSize', $threadStackSizeDescription, 2);
2292 }
2293 }
2294
2295 /**
2296 * Check if PHP function mail() works
2297 *
2298 * @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.
2299 * @return string The mail form if it is requested with get_form
2300 * @todo Define visibility
2301 */
2302 public function check_mail($cmd = '') {
2303 switch ($cmd) {
2304 case 'get_form':
2305 $out = '
2306 <p id="checkMailForm">
2307 You can check the t3lib_mail functionality by entering your email
2308 address here and press the button. You should then
2309 receive a testmail from "typo3installtool@example.org".
2310 </p>
2311 ';
2312 // Get the template file
2313 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'CheckMail.html'));
2314 // Get the template part from the file
2315 $template = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###TEMPLATE###');
2316 if (!empty($this->mailMessage)) {
2317 // Get the subpart for the mail is sent message
2318 $mailSentSubpart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($template, '###MAILSENT###');
2319 }
2320 $template = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($template, '###MAILSENT###', $mailSentSubpart);
2321 // Define the markers content
2322 $markers = array(
2323 'message' => $this->mailMessage,
2324 'enterEmail' => 'Enter the email address',
2325 'actionUrl' => $this->action . '#checkMailForm',
2326 'submit' => 'Send test mail'
2327 );
2328 // Fill the markers
2329 $out .= \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markers, '###|###', TRUE, TRUE);
2330 break;
2331 default:
2332 if (trim($this->INSTALL['check_mail'])) {
2333 $subject = 'TEST SUBJECT';
2334 $email = trim($this->INSTALL['check_mail']);
2335 /** @var $mailMessage \TYPO3\CMS\Core\Mail\MailMessage */
2336 $mailMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
2337 $mailMessage->addTo($email)->addFrom('typo3installtool@example.org', 'TYPO3 Install Tool')->setSubject($subject)->setBody('<html><body>HTML TEST CONTENT</body></html>');
2338 $mailMessage->addPart('TEST CONTENT');
2339 $mailMessage->send();
2340 $this->mailMessage = 'Mail was sent to: ' . $email;
2341 }
2342 break;
2343 }
2344 return $out;
2345 }
2346
2347 /**
2348 * Checking php extensions, specifically GDLib and Freetype
2349 *
2350 * @return void
2351 * @todo Define visibility
2352 */
2353 public function checkExtensions() {
2354 $ext = 'GDLib';
2355 $this->message($ext);
2356 $software_info = 1;
2357 if (extension_loaded('gd') && $this->isGD()) {
2358 $this->config_array['gd'] = 1;
2359 $this->message($ext, 'GDLib found', '', -1);
2360 if ($this->isPNG()) {
2361 $this->config_array['gd_png'] = 1;
2362 $this->message($ext, 'PNG supported', '', -1);
2363 }
2364 if ($this->isGIF()) {
2365 $this->config_array['gd_gif'] = 1;
2366 $this->message($ext, 'GIF supported', '', -1);
2367 }
2368 if ($this->isJPG()) {
2369 $this->config_array['gd_jpg'] = 1;
2370 $this->message($ext, 'JPG supported (not used by TYPO3)', '');
2371 }
2372 if (!$this->config_array['gd_gif'] && !$this->config_array['gd_png']) {
2373 $this->message($ext, 'PNG or GIF not supported', '
2374 <p>
2375 Your GDLib supports either GIF nor PNG. It must support
2376 either one of them.
2377 </p>
2378 ', 2);
2379 } else {
2380 $msg = array();
2381 if ($this->config_array['gd_gif'] && $this->config_array['gd_png']) {
2382 $msg[] = '
2383 <p>
2384 You can choose between generating GIF or PNG files,
2385 as your GDLib supports both.
2386 </p>
2387 ';
2388 }
2389 if ($this->config_array['gd_gif']) {
2390 $msg[] = '
2391 <p>
2392 You should watch out for the generated size of the
2393 GIF-files because some versions of the GD library do
2394 not compress them with LZW, but RLE and ImageMagick
2395 is subsequently used to compress with LZW. But in
2396 the case of ImageMagick failing this task (eg. not
2397 being compiled with LZW which is the case with some
2398 versions) you\'ll end up with GIF-filesizes all too
2399 big!
2400 <br />
2401 This Install Tool tests what kinds of GIF
2402 compression are available in the ImageMagick
2403 installations by a physical test. You can also check
2404 it manually by opening a TYPO3 generated gif-file
2405 with Photoshop and save it in a new file. If the
2406 file sizes of the original and the new file are
2407 almost the same, you\'re having LZW compression and
2408 everything is fine.
2409 </p>
2410 ';
2411 }
2412 if ($this->config_array['gd_png']) {
2413 $msg[] = '
2414 <p>
2415 TYPO3 prefers the use of GIF-files and most likely
2416 your visitors on your website does too as not all
2417 browsers support PNG yet.
2418 </p>
2419 ';
2420 }
2421 $this->message($ext, 'GIF / PNG issues', implode(LF, $msg), 1);
2422 }
2423 if (!$this->isTTF()) {
2424 $this->message($ext, 'FreeType is apparently not installed', '
2425 <p>
2426 It looks like the FreeType library is not compiled into
2427 GDLib. This is required when TYPO3 uses GDLib and
2428 you\'ll most likely get errors like \'ImageTTFBBox is
2429 not a function\' or \'ImageTTFText is not a function\'.
2430 </p>
2431 ', 2);
2432 } else {
2433 $this->message($ext, 'FreeType quick-test (' . ($this->isGIF() ? 'as GIF' : 'as PNG') . ')', '
2434 <p>
2435 <img src="' . htmlspecialchars((\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI') . '&testingTrueTypeSupport=1')) . '" alt="" />
2436 <br />
2437 (If the text is exceeding the image borders you are
2438 using Freetype 2 and need to set
2439 TYPO3_CONF_VARS[GFX][TTFdpi]=96.
2440 <br />
2441 If there is no image at all Freetype is most likely NOT
2442 available and you can just as well disable GDlib for
2443 TYPO3...)
2444 </p>
2445 ', -1);
2446 $this->config_array['freetype'] = 1;
2447 }
2448 } else {
2449 $this->message($ext, 'GDLib2 not found', '
2450 <p>
2451 GDLib2 is required if you want to use the GIFBUILDER object
2452 in TypoScript. GIFBUILDER is in charge of all advanced image
2453 generation in TypoScript, including graphical menuitems.
2454 <br />
2455 GDLib2 is also used in the TYPO3 Backend (TBE) to generate
2456 record icons and new module tabs.
2457 <br />
2458 It\'s highly recommended to install this library. Remember
2459 to compile GD with FreeType which is also required.
2460 <br />
2461 If you choose not to install GDLib, you can disable it in
2462 the configuration with [GFX][gdlib]=0;.
2463 </p>
2464 ', 2);
2465 }
2466 $this->message($ext, 'GDLib software information', $this->getGDSoftwareInfo());
2467 }
2468
2469 /**
2470 * Checking and testing that the required writable directories are writable.
2471 *
2472 * @return void
2473 * @todo Define visibility
2474 */
2475 public function checkDirs() {
2476 // Check typo3/temp/
2477 $ext = 'Directories';
2478 $this->message($ext);
2479 $uniqueName = md5(uniqid(microtime()));
2480 // The requirement level (the integer value, ie. the second value of the value array) has the following meanings:
2481 // -1 = not required, but if it exists may be writable or not
2482 // 0 = not required, if it exists the dir should be writable
2483 // 1 = required, don't has to be writable
2484 // 2 = required, has to be writable
2485 $checkWrite = array(
2486 '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'),
2487 'typo3temp/pics/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
2488 'typo3temp/temp/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
2489 'typo3temp/llxml/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
2490 'typo3temp/cs/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
2491 'typo3temp/GB/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
2492 'typo3temp/locks/' => array('This folder is part of the typo3temp/ section. It needs to be writable, too.', 2, 'dir_typo3temp'),
2493 '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),
2494 'typo3conf/ext/' => array('Location for local extensions. Must be writable if the Extension Manager is supposed to install extensions for this website.', 0),
2495 'typo3conf/l10n/' => array('Location for translations. Must be writable if the Extension Manager is supposed to install translations for extensions.', 0),
2496 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),
2497 'uploads/' => array('Location for uploaded files from RTE, in the subdirectories for uploaded files of content elements.', 2),
2498 'uploads/pics/' => array('Typical location for uploaded files (images especially).', 0),
2499 'uploads/media/' => array('Typical location for uploaded files (non-images especially).', 0),
2500 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] => array('Location for local files such as templates, independent uploads etc.', -1),
2501 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/' => array('Typical temporary location for default upload of files by administrators.', 0)
2502 );
2503 foreach ($checkWrite as $relpath => $descr) {
2504 // Check typo3temp/
2505 $general_message = $descr[0];
2506 // If the directory is missing, try to create it
2507 if (!@is_dir((PATH_site . $relpath))) {
2508 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir(PATH_site . $relpath);
2509 }
2510 if (!@is_dir((PATH_site . $relpath))) {
2511 if ($descr[1]) {
2512 // required...
2513 $this->message($ext, $relpath . ' directory does not exist and could not be created', '
2514 <p>
2515 <em>Full path: ' . PATH_site . $relpath . '</em>
2516 <br />
2517 ' . $general_message . '
2518 </p>
2519 <p>
2520 This error should not occur as ' . $relpath . ' must
2521 always be accessible in the root of a TYPO3 website.
2522 </p>
2523 ', 3);
2524 } else {
2525 if ($descr[1] == 0) {
2526 $msg = 'This directory does not necessarily have to exist but if it does it must be writable.';
2527 } else {
2528 $msg = 'This directory does not necessarily have to exist and if it does it can be writable or not.';
2529 }
2530 $this->message($ext, $relpath . ' directory does not exist', '
2531 <p>
2532 <em>Full path: ' . PATH_site . $relpath . '</em>
2533 <br />
2534 ' . $general_message . '
2535 </p>
2536 <p>
2537 ' . $msg . '
2538 </p>
2539 ', 2);
2540 }
2541 } else {
2542 $file = PATH_site . $relpath . $uniqueName;
2543 @touch($file);
2544 if (@is_file($file)) {
2545 unlink($file);
2546 if ($descr[2]) {
2547 $this->config_array[$descr[2]] = 1;
2548 }
2549 $this->message($ext, $relpath . ' writable', '', -1);
2550 } else {
2551 $severity = $descr[1] == 2 || $descr[1] == 0 ? 3 : 2;
2552 if ($descr[1] == 0 || $descr[1] == 2) {
2553 $msg = 'The directory ' . $relpath . ' must be writable!';
2554 } elseif ($descr[1] == -1 || $descr[1] == 1) {
2555 $msg = 'The directory ' . $relpath . ' does not necessarily have to be writable.';
2556 }
2557 $this->message($ext, $relpath . ' directory not writable', '
2558 <p>
2559 <em>Full path: ' . $file . '</em>
2560 <br />
2561 ' . $general_message . '
2562 </p>
2563 <p>
2564 Tried to write this file (with touch()) but didn\'t
2565 succeed.
2566 <br />
2567 ' . $msg . '
2568 </p>
2569 ', $severity);
2570 }
2571 }
2572 }
2573 }
2574
2575 /**
2576 * Checking for existing ImageMagick installs.
2577 *
2578 * 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.
2579 *
2580 * @param array $paths Possible ImageMagick paths
2581 * @return void
2582 * @todo Define visibility
2583 */
2584 public function checkImageMagick($paths) {
2585 $ext = 'Check Image Magick';
2586 $this->message($ext);
2587 // Get the template file
2588 $templateFile = @file_get_contents((PATH_site . $this->templateFilePath . 'CheckImageMagick.html'));
2589 $paths = array_unique($paths);
2590 $programs = explode(',', 'gm,convert,combine,composite,identify');
2591 $isExt = TYPO3_OS == 'WIN' ? '.exe' : '';
2592 $this->config_array['im_combine_filename'] = 'combine';
2593 foreach ($paths as $k => $v) {
2594 if (!preg_match('/[\\/]$/', $v)) {
2595 $v .= '/';
2596 }
2597 foreach ($programs as $filename) {
2598 if (ini_get('open_basedir') || file_exists($v) && @is_file(($v . $filename . $isExt))) {
2599 $version = $this->_checkImageMagick_getVersion($filename, $v);
2600 if ($version > 0) {
2601 // Assume GraphicsMagick
2602 if ($filename == 'gm') {
2603 $index[$v]['gm'] = $version;
2604 // No need to check for "identify" etc.
2605 continue;
2606 } else {
2607 // Assume ImageMagick
2608 $index[$v][$filename] = $version;
2609 }
2610 }
2611 }
2612 }
2613 if (count($index[$v]) >= 3 || $index[$v]['gm']) {
2614 $this->config_array['im'] = 1;
2615 }
2616 if ($index[$v]['gm'] || !$index[$v]['composite'] && $index[$v]['combine']) {
2617 $this->config_array['im_combine_filename'] = 'combine';
2618 } elseif ($index[$v]['composite'] && !$index[$v]['combine']) {
2619 $this->config_array['im_combine_filename'] = 'composite';
2620 }
2621 if (isset($index[$v]['convert']) && $this->checkIMlzw) {
2622 $index[$v]['gif_capability'] = '' . $this->_checkImageMagickGifCapability($v);
2623 }
2624 }
2625 $this->config_array['im_versions'] = $index;
2626 if (!$this->config_array['im']) {
2627 $this->message($ext, 'No ImageMagick installation available', '
2628 <p>
2629 It seems that there is no adequate ImageMagick installation
2630 available at the checked locations (' . implode(', ', $paths) . ')
2631 <br />
2632 An \'adequate\' installation for requires \'convert\',
2633 \'combine\'/\'composite\' and \'identify\' to be available
2634 </p>
2635 ', 2);
2636 } else {
2637 // Get the subpart for the ImageMagick versions
2638 $theCode = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###VERSIONS###');
2639 // Get the subpart for each ImageMagick version
2640 $rowsSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($theCode, '###ROWS###');
2641 $rows = array();
2642 foreach ($this->config_array['im_versions'] as $p => $v) {
2643 $ka = array();
2644 reset($v);
2645 while (list($ka[]) = each($v)) {
2646
2647 }
2648 // Define the markers content
2649 $rowsMarkers = array(
2650 'file' => $p,
2651 'type' => implode('<br />', $ka),
2652 'version' => implode('<br />', $v)
2653 );
2654 // Fill the markers in the subpart
2655 $rows[] = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($rowsSubPart, $rowsMarkers, '###|###', TRUE, FALSE);
2656 }
2657 // Substitute the subpart for the ImageMagick versions
2658 $theCode = \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($theCode, '###ROWS###', implode(LF, $rows));
2659 // Add the content to the message array
2660 $this->message($ext, 'Available ImageMagick/GraphicsMagick installations:', $theCode, -1);
2661 }
2662 // Get the template file
2663 $formSubPart = \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($templateFile, '###FORM###');
2664 // Define the markers content
2665 $formMarkers = array(
2666 'actionUrl' => $this->action,
2667 'lzwChecked' => $this->INSTALL['checkIM']['lzw'] ? 'checked="checked"' : '',
2668 'lzwLabel' => 'Check LZW capabilities.',
2669 'checkPath' => 'Check this path for ImageMagick installation:',
2670 'imageMagickPath' => htmlspecialchars($this->INSTALL['checkIM']['path']),
2671 'comment' => '(Eg. "D:\\wwwroot\\im537\\ImageMagick\\" for Windows or "/usr/bin/" for Unix)',
2672 'send' => 'Send'
2673 );
2674 // Fill the markers
2675 $formSubPart = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($formSubPart, $formMarkers, '###|###', TRUE, FALSE);
2676 // Add the content to the message array
2677 $this->message($ext, 'Search for ImageMagick:', $formSubPart, 0);
2678 }
2679
2680 /**
2681 * Checking GIF-compression capabilities of ImageMagick install
2682 *
2683 * @param string $path Path of ImageMagick installation
2684 * @return string Type of compression
2685 * @todo Define visibility
2686 */
2687 public function _checkImageMagickGifCapability($path) {
2688 if ($this->config_array['dir_typo3temp']) {
2689 $tempPath = $this->typo3temp_path;
2690 $uniqueName = md5(uniqid(microtime()));
2691 $dest = $tempPath . $uniqueName . '.gif';
2692 $src = $this->backPath . 'gfx/typo3logo.gif';
2693 if (@is_file($src) && !strstr($src, ' ') && !strstr($dest, ' ')) {
2694 $cmd = \TYPO3\CMS\Core\Utility\GeneralUtility::imageMagickCommand('convert', $src . ' ' . $dest, $path);
2695 \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd);
2696 } else {
2697 die('No typo3/gfx/typo3logo.gif file!');
2698 }
2699 $out = '';
2700 if (@is_file($dest)) {
2701 $new_info = @getimagesize($dest);
2702 clearstatcache();
2703 $new_size = filesize($dest);
2704 $src_info = @getimagesize($src);
2705 clearstatcache();
2706 $src_size = @filesize($src);
2707 if ($new_info[0] != $src_info[0] || $new_info[1] != $src_info[1] || !$new_size || !$src_size) {
2708 $out = 'error';
2709 } else {
2710 // NONE-LZW ratio was 5.5 in test
2711 if ($new_size / $src_size > 4) {
2712 $out = 'NONE';
2713 } elseif ($new_size / $src_size > 1.5) {
2714 $out = 'RLE';
2715 } else {
2716 $out = 'LZW';
2717 }
2718 }
2719 unlink($dest);
2720 }
2721 return $out;
2722 }
2723 }
2724
2725 /**
2726 * Extracts the version number for ImageMagick
2727 *
2728 * @param string $file The program name to execute in order to find out the version number
2729 * @param string $path Path for the above program
2730 * @return string Version number of the found ImageMagick instance
2731 * @todo Define visibility
2732 */
2733 public function _checkImageMagick_getVersion($file, $path) {
2734 // Temporarily override some settings
2735 $im_version = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'];
2736 $combine_filename = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'];
2737 if ($file == 'gm') {
2738 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] = 'gm';
2739 // Work-around, preventing execution of "gm gm"
2740 $file = 'identify';
2741 // Work-around - GM doesn't like to be executed without any arguments
2742 $parameters = '-version';
2743 } else {
2744 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] = 'im5';
2745 // Override the combine_filename setting
2746 if ($file == 'combine' || $file == 'composite') {
2747 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'] = $file;
2748 }
2749 }
2750 $cmd = \TYPO3\CMS\Core\Utility\GeneralUtility::imageMagickCommand($file, $parameters, $path);
2751 $retVal = FALSE;
2752 \TYPO3\CMS\Core\Utility\CommandUtility::exec($cmd, $retVal);
2753 $string = $retVal[0];
2754 list(, $ver) = explode('Magick', $string);
2755 list($ver) = explode(' ', trim($ver));
2756 // Restore the values
2757 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_version_5'] = $im_version;
2758 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename'] = $combine_filename;
2759 return trim($ver);
2760 }
2761
2762 /**
2763 * Checks database username/password/host/database
2764 *
2765 * @return void
2766 * @todo Define visibility
2767 */
2768 public function checkDatabase() {
2769 $ext = 'Check database';
2770 $this->message($ext);
2771 if (!extension_loaded('mysql') && !\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('dbal')) {
2772 $this->message($ext, 'MySQL not available', '
2773 <p>
2774 PHP does not feature MySQL support (which is pretty unusual).
2775 </p>
2776 ', 2);
2777 } else {
2778 if (!TYPO3_db_host || !TYPO3_db_username) {
2779 $this->message($ext, 'Username, password or host not set', '
2780 <p>
2781 You may need to enter data for these values:
2782 <br />
2783 Username: <strong>' . htmlspecialchars(TYPO3_db_username) . '</strong>
2784 <br />
2785 Host: <strong>' . htmlspecialchars(TYPO3_db_host) . '</strong>
2786 <br />
2787 <br />
2788 Use the form below.
2789 </p>
2790 ', 2);
2791 }
2792 if ($result = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
2793 $this->message($ext, 'Connected to SQL database successfully', '
2794 <dl id="t3-install-databaseconnected">
2795 <dt>
2796 Username:
2797 </dt>
2798 <dd>
2799 ' . htmlspecialchars(TYPO3_db_username) . '
2800 </dd>
2801 <dt>
2802 Host:
2803 </dt>
2804 <dd>
2805 ' . htmlspecialchars(TYPO3_db_host) . '
2806