[BUGFIX] Add missing htmlspecialchars() or quoteJSvalue()
[Packages/TYPO3.CMS.git] / typo3 / sysext / reports / Classes / Report / Status / ConfigurationStatus.php
1 <?php
2 namespace TYPO3\CMS\Reports\Report\Status;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * Performs some checks about the install tool protection status
21 *
22 * @author Ingo Renner <ingo@typo3.org>
23 */
24 class ConfigurationStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
25
26 /**
27 * 10MB
28 *
29 * @var int
30 */
31 protected $deprecationLogFileSizeWarningThreshold = 10485760;
32
33 /**
34 * 100MB
35 *
36 * @var int
37 */
38 protected $deprecationLogFileSizeErrorThreshold = 104857600;
39
40 /**
41 * Backpath to the typo3 main directory
42 *
43 * @var string
44 */
45 protected $backPath = '../';
46
47 /**
48 * Determines the Install Tool's status, mainly concerning its protection.
49 *
50 * @return array List of statuses
51 */
52 public function getStatus() {
53 $this->executeAdminCommand();
54 $statuses = array(
55 'emptyReferenceIndex' => $this->getReferenceIndexStatus(),
56 'deprecationLog' => $this->getDeprecationLogStatus()
57 );
58 if ($this->isMemcachedUsed()) {
59 $statuses['memcachedConnection'] = $this->getMemcachedConnectionStatus();
60 }
61 if (TYPO3_OS !== 'WIN') {
62 $statuses['createdFilesWorldWritable'] = $this->getCreatedFilesWorldWritableStatus();
63 $statuses['createdDirectoriesWorldWritable'] = $this->getCreatedDirectoriesWorldWritableStatus();
64 }
65 return $statuses;
66 }
67
68 /**
69 * Checks if sys_refindex is empty.
70 *
71 * @return \TYPO3\CMS\Reports\Status An object representing whether the reference index is empty or not
72 */
73 protected function getReferenceIndexStatus() {
74 $value = $GLOBALS['LANG']->getLL('status_ok');
75 $message = '';
76 $severity = \TYPO3\CMS\Reports\Status::OK;
77 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'sys_refindex');
78 $registry = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Registry::class);
79 $lastRefIndexUpdate = $registry->get('core', 'sys_refindex_lastUpdate');
80 if (!$count && $lastRefIndexUpdate) {
81 $value = $GLOBALS['LANG']->getLL('status_empty');
82 $severity = \TYPO3\CMS\Reports\Status::WARNING;
83 $url = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('system_dbint') . '&id=0&SET[function]=refindex';
84 $message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.backend_reference_index'), '<a href="' . htmlspecialchars($url) . '">', '</a>', \TYPO3\CMS\Backend\Utility\BackendUtility::dateTime($lastRefIndexUpdate));
85 }
86 return GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->getLL('status_referenceIndex'), $value, $message, $severity);
87 }
88
89 /**
90 * Checks whether memcached is configured, if that's the case we assume it's also used.
91 *
92 * @return bool TRUE if memcached is used, FALSE otherwise.
93 */
94 protected function isMemcachedUsed() {
95 $memcachedUsed = FALSE;
96 $memcachedServers = $this->getConfiguredMemcachedServers();
97 if (count($memcachedServers)) {
98 $memcachedUsed = TRUE;
99 }
100 return $memcachedUsed;
101 }
102
103 /**
104 * Gets the configured memcached server connections.
105 *
106 * @return array An array of configured memcached server connections.
107 */
108 protected function getConfiguredMemcachedServers() {
109 $memcachedServers = array();
110 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'])) {
111 foreach ($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] as $table => $conf) {
112 if (is_array($conf)) {
113 foreach ($conf as $key => $value) {
114 if (!is_array($value) && $value === 'TYPO3\\CMS\\Core\\Cache\\Backend\\MemcachedBackend') {
115 $memcachedServers = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$table]['options']['servers'];
116 break;
117 }
118 }
119 }
120 }
121 }
122 return $memcachedServers;
123 }
124
125 /**
126 * Checks whether TYPO3 can connect to the configured memcached servers.
127 *
128 * @return \TYPO3\CMS\Reports\Status An object representing whether TYPO3 can connect to the configured memcached servers
129 */
130 protected function getMemcachedConnectionStatus() {
131 $value = $GLOBALS['LANG']->getLL('status_ok');
132 $message = '';
133 $severity = \TYPO3\CMS\Reports\Status::OK;
134 $failedConnections = array();
135 $defaultMemcachedPort = ini_get('memcache.default_port');
136 $memcachedServers = $this->getConfiguredMemcachedServers();
137 if (function_exists('memcache_connect') && is_array($memcachedServers)) {
138 foreach ($memcachedServers as $testServer) {
139 $configuredServer = $testServer;
140 if (substr($testServer, 0, 7) == 'unix://') {
141 $host = $testServer;
142 $port = 0;
143 } else {
144 if (substr($testServer, 0, 6) === 'tcp://') {
145 $testServer = substr($testServer, 6);
146 }
147 if (strstr($testServer, ':') !== FALSE) {
148 list($host, $port) = explode(':', $testServer, 2);
149 } else {
150 $host = $testServer;
151 $port = $defaultMemcachedPort;
152 }
153 }
154 $memcachedConnection = @memcache_connect($host, $port);
155 if ($memcachedConnection != NULL) {
156 memcache_close($memcachedConnection);
157 } else {
158 $failedConnections[] = $configuredServer;
159 }
160 }
161 }
162 if (count($failedConnections)) {
163 $value = $GLOBALS['LANG']->getLL('status_connectionFailed');
164 $severity = \TYPO3\CMS\Reports\Status::WARNING;
165 $message = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.memcache_not_usable') . '<br /><br />' . '<ul><li>' . implode('</li><li>', $failedConnections) . '</li></ul>';
166 }
167 return GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->getLL('status_memcachedConfiguration'), $value, $message, $severity);
168 }
169
170 /**
171 * Provides status information on the deprecation log, whether it's enabled
172 * and if so whether certain limits in file size are reached.
173 *
174 * @return \TYPO3\CMS\Reports\Status The deprecation log status.
175 */
176 protected function getDeprecationLogStatus() {
177 $title = $GLOBALS['LANG']->getLL('status_configuration_DeprecationLog');
178 $value = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:disabled');
179 $message = '';
180 $severity = \TYPO3\CMS\Reports\Status::OK;
181 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['enableDeprecationLog']) {
182 $value = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:enabled');
183 $message = '<p>' . $GLOBALS['LANG']->getLL('status_configuration_DeprecationLogEnabled') . '</p>';
184 $severity = \TYPO3\CMS\Reports\Status::NOTICE;
185 $logFile = GeneralUtility::getDeprecationLogFileName();
186 $logFileSize = 0;
187 if (@file_exists($logFile)) {
188 $logFileSize = filesize($logFile);
189 $message .= '<p>' . sprintf($GLOBALS['LANG']->getLL('status_configuration_DeprecationLogFile'), $this->getDeprecationLogFileLink()) . '</p>';
190 $removeDeprecationLogFileUrl = GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL') . '&amp;adminCmd=removeDeprecationLogFile';
191 $message .= '<p>' . sprintf($GLOBALS['LANG']->getLL('status_configuration_DeprecationLogSize'), GeneralUtility::formatSize($logFileSize)) . ' <a href="' . $removeDeprecationLogFileUrl . '">' . $GLOBALS['LANG']->getLL('status_configuration_DeprecationLogDeleteLink') . '</a></p>';
192 }
193 if ($logFileSize > $this->deprecationLogFileSizeWarningThreshold) {
194 $severity = \TYPO3\CMS\Reports\Status::WARNING;
195 }
196 if ($logFileSize > $this->deprecationLogFileSizeErrorThreshold) {
197 $severity = \TYPO3\CMS\Reports\Status::ERROR;
198 }
199 }
200 return GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $title, $value, $message, $severity);
201 }
202
203 /**
204 * Warning, if fileCreateMask has write bit for 'others' set.
205 *
206 * @return \TYPO3\CMS\Reports\Status The writable status for 'others'
207 */
208 protected function getCreatedFilesWorldWritableStatus() {
209 $value = $GLOBALS['LANG']->getLL('status_ok');
210 $message = '';
211 $severity = \TYPO3\CMS\Reports\Status::OK;
212 if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] % 10 & 2) {
213 $value = $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'];
214 $severity = \TYPO3\CMS\Reports\Status::WARNING;
215 $message = $GLOBALS['LANG']->getLL('status_CreatedFilePermissions.writable');
216 }
217 return GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->getLL('status_CreatedFilePermissions'), $value, $message, $severity);
218 }
219
220 /**
221 * Warning, if folderCreateMask has write bit for 'others' set.
222 *
223 * @return \TYPO3\CMS\Reports\Status The writable status for 'others'
224 */
225 protected function getCreatedDirectoriesWorldWritableStatus() {
226 $value = $GLOBALS['LANG']->getLL('status_ok');
227 $message = '';
228 $severity = \TYPO3\CMS\Reports\Status::OK;
229 if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] % 10 & 2) {
230 $value = $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'];
231 $severity = \TYPO3\CMS\Reports\Status::WARNING;
232 $message = $GLOBALS['LANG']->getLL('status_CreatedDirectoryPermissions.writable');
233 }
234 return GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->getLL('status_CreatedDirectoryPermissions'), $value, $message, $severity);
235 }
236
237 /**
238 * Creates a link to the deprecation log file with the absolute path as the
239 * link text.
240 *
241 * @return string Link to the deprecation log file
242 */
243 protected function getDeprecationLogFileLink() {
244 $logFile = GeneralUtility::getDeprecationLogFileName();
245 $relativePath = GeneralUtility::resolveBackPath($this->backPath . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($logFile));
246 $link = '<a href="' . $relativePath . '">' . $logFile . '</a>';
247 return $link;
248 }
249
250 /**
251 * Executes admin commands.
252 *
253 * Currently implemented commands are:
254 * - Remove deprecation log file
255 *
256 * @return void
257 */
258 protected function executeAdminCommand() {
259 $command = GeneralUtility::_GET('adminCmd');
260 switch ($command) {
261 case 'removeDeprecationLogFile':
262 self::removeDeprecationLogFile();
263 break;
264 default:
265 // intentionally left blank
266 }
267 }
268
269 /**
270 * Remove deprecation log file.
271 *
272 * @return void
273 */
274 static protected function removeDeprecationLogFile() {
275 if (@unlink(GeneralUtility::getDeprecationLogFileName())) {
276 $message = $GLOBALS['LANG']->getLL('status_configuration_DeprecationLogDeletedSuccessful');
277 $severity = \TYPO3\CMS\Core\Messaging\FlashMessage::OK;
278 } else {
279 $message = $GLOBALS['LANG']->getLL('status_configuration_DeprecationLogDeletionFailed');
280 $severity = \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR;
281 }
282 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $message, '', $severity, TRUE);
283 /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
284 $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
285 /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
286 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
287 $defaultFlashMessageQueue->enqueue($flashMessage);
288 }
289
290 }