[!!!][TASK] Remove deprecated code from sysext core
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / File / ExtendedFileUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility\File;
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\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Messaging\FlashMessage;
20 use TYPO3\CMS\Core\Resource\File;
21 use TYPO3\CMS\Core\Resource\Folder;
22 use TYPO3\CMS\Core\Resource\ResourceFactory;
23 use TYPO3\CMS\Core\Resource\ResourceStorage;
24 use TYPO3\CMS\Core\Utility\CommandUtility;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Core\Utility\PathUtility;
27
28 /**
29 * Contains functions for performing file operations like copying, pasting, uploading, moving,
30 * deleting etc. through the TCE
31 *
32 * See document "TYPO3 Core API" for syntax
33 *
34 * This class contains functions primarily used by tce_file.php (TYPO3 Core Engine for file manipulation)
35 * Functions include copying, moving, deleting, uploading and so on...
36 *
37 * Important internal variables:
38 *
39 * $filemounts (see basicFileFunctions)
40 * $f_ext (see basicFileFunctions)
41 *
42 * All fileoperations must be within the filemount-paths. Further the fileextension
43 * MUST validate TRUE with the f_ext array
44 *
45 * The unzip-function allows unzip only if the destination path has it's f_ext[]['allow'] set to '*'!!
46 * You are allowed to copy/move folders within the same 'space' (web/ftp).
47 * You are allowed to copy/move folders between spaces (web/ftp) IF the destination has it's f_ext[]['allow'] set to '*'!
48 *
49 * Advice:
50 * You should always exclude php-files from the webspace. This will keep people from uploading, copy/moving and renaming files to become executable php scripts.
51 * You should never mount a ftp_space 'below' the webspace so that it reaches into the webspace. This is because if somebody unzips a zip-file in the ftp-space so that it reaches out into the webspace this will be a violation of the safety
52 * For example this is a bad idea: you have an ftp-space that is '/www/' and a web-space that is '/www/htdocs/'
53 *
54 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
55 */
56 class ExtendedFileUtility extends BasicFileUtility {
57
58 // External static variables:
59 // Notice; some of these are overridden in the start() method with values from $GLOBALS['TYPO3_CONF_VARS']['BE']
60 // Path to unzip-program (with trailing '/')
61 /**
62 * @var string
63 */
64 public $unzipPath = '';
65
66 // If set, the uploaded files will overwrite existing files.
67 /**
68 * @var bool
69 */
70 public $dontCheckForUnique = 0;
71
72 /**
73 * This array is self-explaining (look in the class below).
74 * It grants access to the functions. This could be set from outside in order to enabled functions to users.
75 * See also the function setActionPermissions() which takes input directly from the user-record
76 *
77 * @var array
78 */
79 public $actionPerms = array(
80 // File permissions
81 'addFile' => FALSE,
82 'readFile' => FALSE,
83 'writeFile' => FALSE,
84 'copyFile' => FALSE,
85 'moveFile' => FALSE,
86 'renameFile' => FALSE,
87 'unzipFile' => FALSE,
88 'deleteFile' => FALSE,
89 // Folder permissions
90 'addFolder' => FALSE,
91 'readFolder' => FALSE,
92 'writeFolder' => FALSE,
93 'copyFolder' => FALSE,
94 'moveFolder' => FALSE,
95 'renameFolder' => FALSE,
96 'deleteFolder' => FALSE,
97 'recursivedeleteFolder' => FALSE
98 );
99
100 // This is regarded to be the recycler folder
101 /**
102 * @var string
103 */
104 public $recyclerFN = '_recycler_';
105
106 // Internal, dynamic
107 // Will contain map between upload ID and the final filename
108 /**
109 * @var array
110 */
111 public $internalUploadMap = array();
112
113 /**
114 * @var string
115 */
116 public $lastError = '';
117
118 /**
119 * All error messages from the file operations of this script instance
120 *
121 * @var array
122 */
123 protected $errorMessages = array();
124
125 /**
126 * @var array
127 */
128 protected $fileCmdMap;
129
130 /**
131 * The File Factory
132 *
133 * @var \TYPO3\CMS\Core\Resource\ResourceFactory
134 */
135 protected $fileFactory;
136
137
138 /**
139 * Initialization of the class
140 *
141 * @param array $fileCmds Array with the commands to execute. See "TYPO3 Core API" document
142 * @return void
143 */
144 public function start($fileCmds) {
145 $unzipPath = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path']);
146 if (substr($unzipPath, -1) !== '/' && is_dir($unzipPath)) {
147 // Make sure the path ends with a slash
148 $unzipPath .= '/';
149 }
150 $this->unzipPath = $unzipPath;
151 // Initialize Object Factory
152 $this->fileFactory = ResourceFactory::getInstance();
153 // Initializing file processing commands:
154 $this->fileCmdMap = $fileCmds;
155 }
156
157 /**
158 * Sets the file action permissions.
159 * If no argument is given, permissions of the currently logged in backend user are taken into account.
160 *
161 * @param array $permissions File Permissions.
162 */
163 public function setActionPermissions(array $permissions = array()) {
164 if (empty($permissions)) {
165 $permissions = $GLOBALS['BE_USER']->getFilePermissions();
166 }
167 $this->actionPerms = $permissions;
168 }
169
170 /**
171 * Processing the command array in $this->fileCmdMap
172 *
173 * @return mixed FALSE, if the file functions were not initialized
174 * @throws \UnexpectedValueException
175 */
176 public function processData() {
177 $result = array();
178 if (!$this->isInit) {
179 return FALSE;
180 }
181 if (is_array($this->fileCmdMap)) {
182 // Check if there were uploads expected, but no one made
183 if ($this->fileCmdMap['upload']) {
184 $uploads = $this->fileCmdMap['upload'];
185 foreach ($uploads as $upload) {
186 if (empty($_FILES[('upload_' . $upload['data'])]['name'])
187 || (is_array($_FILES[('upload_' . $upload['data'])]['name'])
188 && empty($_FILES[('upload_' . $upload['data'])]['name'][0])
189 )
190 ) {
191 unset($this->fileCmdMap['upload'][$upload['data']]);
192 }
193 }
194 if (count($this->fileCmdMap['upload']) == 0) {
195 $this->writelog(1, 1, 108, 'No file was uploaded!', '');
196 }
197 }
198
199 // Check if there were new folder names expected, but non given
200 if ($this->fileCmdMap['newfolder']) {
201 foreach ($this->fileCmdMap['newfolder'] as $key => $cmdArr) {
202 if (empty($cmdArr['data'])) {
203 unset($this->fileCmdMap['newfolder'][$key]);
204 }
205 }
206 if (count($this->fileCmdMap['newfolder']) === 0) {
207 $this->writeLog(6, 1, 108, 'No name for new folder given!', '');
208 }
209 }
210
211 // Traverse each set of actions
212 foreach ($this->fileCmdMap as $action => $actionData) {
213 // Traverse all action data. More than one file might be affected at the same time.
214 if (is_array($actionData)) {
215 $result[$action] = array();
216 foreach ($actionData as $cmdArr) {
217 // Clear file stats
218 clearstatcache();
219 // Branch out based on command:
220 switch ($action) {
221 case 'delete':
222 $result[$action][] = $this->func_delete($cmdArr);
223 break;
224 case 'copy':
225 $result[$action][] = $this->func_copy($cmdArr);
226 break;
227 case 'move':
228 $result[$action][] = $this->func_move($cmdArr);
229 break;
230 case 'rename':
231 $result[$action][] = $this->func_rename($cmdArr);
232 break;
233 case 'newfolder':
234 $result[$action][] = $this->func_newfolder($cmdArr);
235 break;
236 case 'newfile':
237 $result[$action][] = $this->func_newfile($cmdArr);
238 break;
239 case 'editfile':
240 $result[$action][] = $this->func_edit($cmdArr);
241 break;
242 case 'upload':
243 $result[$action][] = $this->func_upload($cmdArr);
244 break;
245 case 'unzip':
246 $result[$action][] = $this->func_unzip($cmdArr);
247 break;
248 }
249 // Hook for post-processing the action
250 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'])) {
251 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'] as $classRef) {
252 $hookObject = GeneralUtility::getUserObj($classRef);
253 if (!$hookObject instanceof ExtendedFileUtilityProcessDataHookInterface) {
254 throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Core\\Utility\\File\\ExtendedFileUtilityProcessDataHookInterface', 1279719168);
255 }
256 $hookObject->processData_postProcessAction($action, $cmdArr, $result[$action], $this);
257 }
258 }
259 }
260 }
261 }
262 }
263 return $result;
264 }
265
266 /**
267 * Adds all log error messages from the operations of this script instance to the FlashMessageQueue
268 *
269 * @return void
270 */
271 public function pushErrorMessagesToFlashMessageQueue() {
272 foreach ($this->getErrorMessages() as $msg) {
273 $flashMessage = GeneralUtility::makeInstance(
274 'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
275 $msg,
276 '',
277 FlashMessage::ERROR,
278 TRUE
279 );
280 $this->addFlashMessage($flashMessage);
281 }
282 }
283
284 /**
285 * Return all error messages from the file operations of this script instance
286 *
287 * @return array all errorMessages as a numerical array
288 */
289 public function getErrorMessages() {
290 return $this->errorMessages;
291 }
292
293 /**
294 * @param int $action The action number. See the functions in the class for a hint. Eg. edit is '9', upload is '1' ...
295 * @param int $error The severity: 0 = message, 1 = error, 2 = System Error, 3 = security notice (admin)
296 * @param int $details_nr This number is unique for every combination of $type and $action. This is the error-message number, which can later be used to translate error messages.
297 * @param string $details This is the default, raw error message in english
298 * @param array $data Array with special information that may go into $details by "%s" marks / sprintf() when the log is shown
299 * @return void
300 */
301 public function writeLog($action, $error, $details_nr, $details, $data) {
302 // Type value for tce_file.php
303 $type = 2;
304 if (is_object($this->getBackendUser())) {
305 $this->getBackendUser()->writelog($type, $action, $error, $details_nr, $details, $data);
306 }
307 if ($error > 0) {
308 $this->lastError = vsprintf($details, $data);
309 $this->errorMessages[] = $this->lastError;
310 }
311 }
312
313 /*************************************
314 *
315 * File operation functions
316 *
317 **************************************/
318 /**
319 * Deleting files and folders (action=4)
320 *
321 * @param array $cmds $cmds['data'] is the file/folder to delete
322 * @return bool Returns TRUE upon success
323 */
324 public function func_delete($cmds) {
325 $result = FALSE;
326 if (!$this->isInit) {
327 return $result;
328 }
329 // Example indentifier for $cmds['data'] => "4:mypath/tomyfolder/myfile.jpg"
330 // for backwards compatibility: the combined file identifier was the path+filename
331 $fileObject = $this->getFileObject($cmds['data']);
332 // @todo implement the recycler feature which has been removed from the original implementation
333 // checks to delete the file
334 if ($fileObject instanceof File) {
335 // check if the file still has references
336 // Exclude sys_file_metadata records as these are no use references
337 $refIndexRecords = $this->getDatabaseConnection()->exec_SELECTgetRows(
338 '*',
339 'sys_refindex',
340 'deleted=0 AND ref_table="sys_file" AND ref_uid=' . (int)$fileObject->getUid()
341 . ' AND tablename != "sys_file_metadata"'
342 );
343 if (count($refIndexRecords) > 0) {
344 $shortcutContent = array();
345 foreach ($refIndexRecords as $fileReferenceRow) {
346 $row = $fileReferenceRow;
347 if ($fileReferenceRow['tablename'] === 'sys_file_reference') {
348 $row = $this->transformFileReferenceToRecordReference($fileReferenceRow);
349 }
350 $shortcutRecord = BackendUtility::getRecord($row['tablename'], $row['recuid']);
351 $icon = IconUtility::getSpriteIconForRecord($row['tablename'], $shortcutRecord);
352 $onClick = 'Clickmenu.show("' . $row['tablename'] . '", "' . $row['recuid'] . '", "1", "+info,history,edit", "|", "");return false;';
353 $shortcutContent[] = '<a href="#" oncontextmenu="this.click();return false;" onclick="' . htmlspecialchars($onClick) . '">' . $icon . '</a>' . htmlspecialchars((BackendUtility::getRecordTitle($row['tablename'], $shortcutRecord) . ' [' . BackendUtility::getRecordPath($shortcutRecord['pid'], '', 80) . ']'));
354 }
355
356 // render a message that the file could not be deleted
357 $flashMessage = GeneralUtility::makeInstance(
358 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
359 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.fileNotDeletedHasReferences'), $fileObject->getName()) . '<br />' . implode('<br />', $shortcutContent),
360 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.fileNotDeletedHasReferences'),
361 FlashMessage::WARNING,
362 TRUE
363 );
364 $this->addFlashMessage($flashMessage);
365 } else {
366 try {
367 $result = $fileObject->delete();
368
369 // show the user that the file was deleted
370 $flashMessage = GeneralUtility::makeInstance(
371 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
372 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.fileDeleted'), $fileObject->getName()),
373 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.fileDeleted'),
374 FlashMessage::OK,
375 TRUE
376 );
377 $this->addFlashMessage($flashMessage);
378 // Log success
379 $this->writelog(4, 0, 1, 'File "%s" deleted', array($fileObject->getIdentifier()));
380 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
381 $this->writelog(4, 1, 112, 'You are not allowed to access the file', array($fileObject->getIdentifier()));
382 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
383 $this->writelog(4, 1, 111, 'Target was not within your mountpoints! T="%s"', array($fileObject->getIdentifier()));
384 } catch (\RuntimeException $e) {
385 $this->writelog(4, 1, 110, 'Could not delete file "%s". Write-permission problem?', array($fileObject->getIdentifier()));
386 }
387 }
388 } else {
389 try {
390 /** @var $fileObject \TYPO3\CMS\Core\Resource\FolderInterface */
391 if ($fileObject->getFileCount() > 0) {
392 // render a message that the folder could not be deleted because it still contains files
393 $flashMessage = GeneralUtility::makeInstance(
394 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
395 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.folderNotDeletedHasFiles'), $fileObject->getName()),
396 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.folderNotDeletedHasFiles'),
397 FlashMessage::WARNING,
398 TRUE
399 );
400 $this->addFlashMessage($flashMessage);
401 } else {
402 $result = $fileObject->delete(TRUE);
403
404 // notify the user that the folder was deleted
405 $flashMessage = GeneralUtility::makeInstance(
406 '\\TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
407 sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.description.folderDeleted'), $fileObject->getName()),
408 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:message.header.folderDeleted'),
409 FlashMessage::OK,
410 TRUE
411 );
412 $this->addFlashMessage($flashMessage);
413 // Log success
414 $this->writelog(4, 0, 3, 'Directory "%s" deleted', array($fileObject->getIdentifier()));
415 }
416
417 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException $e) {
418 $this->writelog(4, 1, 123, 'You are not allowed to access the directory', array($fileObject->getIdentifier()));
419 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
420 $this->writelog(4, 1, 121, 'Target was not within your mountpoints! T="%s"', array($fileObject->getIdentifier()));
421 } catch (\RuntimeException $e) {
422 $this->writelog(4, 1, 120, 'Could not delete directory! Write-permission problem? Is directory "%s" empty? (You are not allowed to delete directories recursively).', array($fileObject->getIdentifier()));
423 }
424 }
425 return $result;
426 }
427
428 /**
429 * Maps results from the fal file reference table on the
430 * structure of the normal reference index table.
431 *
432 * @param array $referenceRecord
433 * @return array
434 */
435 protected function transformFileReferenceToRecordReference(array $referenceRecord) {
436 $fileReference = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
437 '*',
438 'sys_file_reference',
439 'uid=' . (int)$referenceRecord['recuid']
440 );
441 return array(
442 'recuid' => $fileReference['uid_foreign'],
443 'tablename' => $fileReference['tablenames'],
444 'field' => $fileReference['fieldname'],
445 'flexpointer' => '',
446 'softref_key' => '',
447 'sorting' => $fileReference['sorting_foreign']
448 );
449 }
450
451 /**
452 * Gets a File or a Folder object from an identifier [storage]:[fileId]
453 *
454 * @param string $identifier
455 * @return \TYPO3\CMS\Core\Resource\Folder|\TYPO3\CMS\Core\Resource\File
456 * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidFileException
457 */
458 protected function getFileObject($identifier) {
459 $object = $this->fileFactory->retrieveFileOrFolderObject($identifier);
460 if (!is_object($object)) {
461 throw new \TYPO3\CMS\Core\Resource\Exception\InvalidFileException('The item ' . $identifier . ' was not a file or directory!!', 1320122453);
462 }
463 if ($object->getStorage()->getUid() === 0) {
464 throw new \TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1375889830);
465 }
466 return $object;
467 }
468
469 /**
470 * Copying files and folders (action=2)
471 *
472 * $cmds['data'] (string): The file/folder to copy
473 * + example "4:mypath/tomyfolder/myfile.jpg")
474 * + for backwards compatibility: the identifier was the path+filename
475 * $cmds['target'] (string): The path where to copy to.
476 * + example "2:targetpath/targetfolder/"
477 * $cmds['altName'] (string): Use an alternative name if the target already exists
478 *
479 * @param array $cmds Command details as described above
480 * @return \TYPO3\CMS\Core\Resource\File
481 */
482 protected function func_copy($cmds) {
483 if (!$this->isInit) {
484 return FALSE;
485 }
486 $sourceFileObject = $this->getFileObject($cmds['data']);
487 /** @var $targetFolderObject \TYPO3\CMS\Core\Resource\Folder */
488 $targetFolderObject = $this->getFileObject($cmds['target']);
489 // Basic check
490 if (!$targetFolderObject instanceof Folder) {
491 $this->writelog(2, 2, 100, 'Destination "%s" was not a directory', array($cmds['target']));
492 return FALSE;
493 }
494 // If this is TRUE, we append _XX to the file name if
495 $appendSuffixOnConflict = (string) $cmds['altName'];
496 $resultObject = NULL;
497 // Copying the file
498 if ($sourceFileObject instanceof File) {
499 try {
500 $conflictMode = $appendSuffixOnConflict !== '' ? 'renameNewFile' : 'cancel';
501 $resultObject = $sourceFileObject->copyTo($targetFolderObject, NULL, $conflictMode);
502 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
503 $this->writelog(2, 1, 114, 'You are not allowed to copy files', '');
504 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
505 $this->writelog(2, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
506 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
507 $this->writelog(2, 1, 111, 'Extension of file name "%s" is not allowed in "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
508 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
509 $this->writelog(2, 1, 112, 'File "%s" already exists in folder "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
510 } catch (\BadMethodCallException $e) {
511 $this->writelog(3, 1, 128, 'The function to copy a file between storages is not yet implemented', array());
512 } catch (\RuntimeException $e) {
513 $this->writelog(2, 2, 109, 'File "%s" WAS NOT copied to "%s"! Write-permission problem?', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
514 }
515 if ($resultObject) {
516 $this->writelog(2, 0, 1, 'File "%s" copied to "%s"', array($sourceFileObject->getIdentifier(), $resultObject->getIdentifier()));
517 }
518 } else {
519 // Else means this is a Folder
520 $sourceFolderObject = $sourceFileObject;
521 try {
522 $conflictMode = $appendSuffixOnConflict !== '' ? 'renameNewFile' : 'cancel';
523 $resultObject = $sourceFolderObject->copyTo($targetFolderObject, NULL, $conflictMode);
524 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
525 $this->writelog(2, 1, 125, 'You are not allowed to copy directories', '');
526 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
527 $this->writelog(2, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
528 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException $e) {
529 $this->writelog(2, 1, 121, 'You don\'t have full access to the destination directory "%s"!', array($targetFolderObject->getIdentifier()));
530 } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException $e) {
531 $this->writelog(2, 1, 122, 'Destination cannot be inside the target! D="%s", T="%s"', array($targetFolderObject->getIdentifier(), $sourceFolderObject->getIdentifier()));
532 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException $e) {
533 $this->writelog(2, 1, 123, 'Target "%s" already exists!', array($targetFolderObject->getIdentifier()));
534 } catch (\BadMethodCallException $e) {
535 $this->writelog(3, 1, 129, 'The function to copy a folder between storages is not yet implemented', array());
536 } catch (\RuntimeException $e) {
537 $this->writelog(2, 2, 119, 'Directory "%s" WAS NOT copied to "%s"! Write-permission problem?', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
538 }
539 if ($resultObject) {
540 $this->writelog(2, 0, 2, 'Directory "%s" copied to "%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
541 }
542 }
543 return $resultObject;
544 }
545
546 /**
547 * Moving files and folders (action=3)
548 *
549 * $cmds['data'] (string): The file/folder to move
550 * + example "4:mypath/tomyfolder/myfile.jpg")
551 * + for backwards compatibility: the identifier was the path+filename
552 * $cmds['target'] (string): The path where to move to.
553 * + example "2:targetpath/targetfolder/"
554 * $cmds['altName'] (string): Use an alternative name if the target already exists
555 *
556 * @param array $cmds Command details as described above
557 * @return \TYPO3\CMS\Core\Resource\File
558 */
559 protected function func_move($cmds) {
560 if (!$this->isInit) {
561 return FALSE;
562 }
563 $sourceFileObject = $this->getFileObject($cmds['data']);
564 $targetFolderObject = $this->getFileObject($cmds['target']);
565 // Basic check
566 if (!$targetFolderObject instanceof Folder) {
567 $this->writelog(3, 2, 100, 'Destination "%s" was not a directory', array($cmds['target']));
568 return FALSE;
569 }
570 $alternativeName = (string) $cmds['altName'];
571 $resultObject = NULL;
572 // Moving the file
573 if ($sourceFileObject instanceof File) {
574 try {
575 if ($alternativeName !== '') {
576 // Don't allow overwriting existing files, but find a new name
577 $resultObject = $sourceFileObject->moveTo($targetFolderObject, $alternativeName, 'renameNewFile');
578 } else {
579 // Don't allow overwriting existing files
580 $resultObject = $sourceFileObject->moveTo($targetFolderObject, NULL, 'cancel');
581 }
582 $this->writelog(3, 0, 1, 'File "%s" moved to "%s"', array($sourceFileObject->getIdentifier(), $resultObject->getIdentifier()));
583 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
584 $this->writelog(3, 1, 114, 'You are not allowed to move files', '');
585 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
586 $this->writelog(3, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
587 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
588 $this->writelog(3, 1, 111, 'Extension of file name "%s" is not allowed in "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
589 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
590 $this->writelog(3, 1, 112, 'File "%s" already exists in folder "%s"!', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
591 } catch (\BadMethodCallException $e) {
592 $this->writelog(3, 1, 126, 'The function to move a file between storages is not yet implemented', array());
593 } catch (\RuntimeException $e) {
594 $this->writelog(3, 2, 109, 'File "%s" WAS NOT copied to "%s"! Write-permission problem?', array($sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()));
595 }
596 } else {
597 // Else means this is a Folder
598 $sourceFolderObject = $sourceFileObject;
599 try {
600 if ($alternativeName !== '') {
601 // Don't allow overwriting existing files, but find a new name
602 $resultObject = $sourceFolderObject->moveTo($targetFolderObject, $alternativeName, 'renameNewFile');
603 } else {
604 // Don't allow overwriting existing files
605 $resultObject = $sourceFolderObject->moveTo($targetFolderObject, NULL, 'renameNewFile');
606 }
607 $this->writelog(3, 0, 2, 'Directory "%s" moved to "%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
608 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
609 $this->writelog(3, 1, 125, 'You are not allowed to move directories', '');
610 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException $e) {
611 $this->writelog(3, 1, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
612 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException $e) {
613 $this->writelog(3, 1, 121, 'You don\'t have full access to the destination directory "%s"!', array($targetFolderObject->getIdentifier()));
614 } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException $e) {
615 $this->writelog(3, 1, 122, 'Destination cannot be inside the target! D="%s", T="%s"', array($targetFolderObject->getIdentifier(), $sourceFolderObject->getIdentifier()));
616 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException $e) {
617 $this->writelog(3, 1, 123, 'Target "%s" already exists!', array($targetFolderObject->getIdentifier()));
618 } catch (\BadMethodCallException $e) {
619 $this->writelog(3, 1, 127, 'The function to move a folder between storages is not yet implemented', array());
620 } catch (\RuntimeException $e) {
621 $this->writelog(3, 2, 119, 'Directory "%s" WAS NOT moved to "%s"! Write-permission problem?', array($sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()));
622 }
623 }
624 return $resultObject;
625 }
626
627 /**
628 * Renaming files or foldes (action=5)
629 *
630 * $cmds['data'] (string): The file/folder to copy
631 * + example "4:mypath/tomyfolder/myfile.jpg")
632 * + for backwards compatibility: the identifier was the path+filename
633 * $cmds['target'] (string): New name of the file/folder
634 *
635 * @param array $cmds Command details as described above
636 * @return \TYPO3\CMS\Core\Resource\File Returns the new file upon success
637 */
638 public function func_rename($cmds) {
639 if (!$this->isInit) {
640 return FALSE;
641 }
642 $sourceFileObject = $this->getFileObject($cmds['data']);
643 $targetFile = $cmds['target'];
644 $resultObject = NULL;
645 if ($sourceFileObject instanceof File) {
646 try {
647 // Try to rename the File
648 $resultObject = $sourceFileObject->rename($targetFile);
649 $this->writelog(5, 0, 1, 'File renamed from "%s" to "%s"', array($sourceFileObject->getName(), $targetFile));
650 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
651 $this->writelog(5, 1, 102, 'You are not allowed to rename files!', '');
652 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
653 $this->writelog(5, 1, 101, 'Extension of file name "%s" or "%s" was not allowed!', array($sourceFileObject->getName(), $targetFile));
654 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
655 $this->writelog(5, 1, 120, 'Destination "%s" existed already!', array($targetFile));
656 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
657 $this->writelog(5, 1, 121, 'Destination path "%s" was not within your mountpoints!', array($targetFile));
658 } catch (\RuntimeException $e) {
659 $this->writelog(5, 1, 100, 'File "%s" was not renamed! Write-permission problem in "%s"?', array($sourceFileObject->getName(), $targetFile));
660 }
661 } else {
662 // Else means this is a Folder
663 try {
664 // Try to rename the Folder
665 $resultObject = $sourceFileObject->rename($targetFile);
666 $this->writelog(5, 0, 2, 'Directory renamed from "%s" to "%s"', array($sourceFileObject->getName(), $targetFile));
667 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
668 $this->writelog(5, 1, 111, 'You are not allowed to rename directories!', '');
669 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
670 $this->writelog(5, 1, 120, 'Destination "%s" existed already!', array($targetFile));
671 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
672 $this->writelog(5, 1, 121, 'Destination path "%s" was not within your mountpoints!', array($targetFile));
673 } catch (\RuntimeException $e) {
674 $this->writelog(5, 1, 110, 'Directory "%s" was not renamed! Write-permission problem in "%s"?', array($sourceFileObject->getName(), $targetFile));
675 }
676 }
677 return $resultObject;
678 }
679
680 /**
681 * This creates a new folder. (action=6)
682 *
683 * $cmds['data'] (string): The new folder name
684 * $cmds['target'] (string): The path where to copy to.
685 * + example "2:targetpath/targetfolder/"
686 *
687 * @param array $cmds Command details as described above
688 * @return \TYPO3\CMS\Core\Resource\Folder Returns the new foldername upon success
689 */
690 public function func_newfolder($cmds) {
691 if (!$this->isInit) {
692 return FALSE;
693 }
694 $targetFolderObject = $this->getFileObject($cmds['target']);
695 if (!$targetFolderObject instanceof Folder) {
696 $this->writelog(6, 2, 104, 'Destination "%s" was not a directory', array($cmds['target']));
697 return FALSE;
698 }
699 $resultObject = NULL;
700 try {
701 $folderName = $cmds['data'];
702 $resultObject = $targetFolderObject->createFolder($folderName);
703 $this->writelog(6, 0, 1, 'Directory "%s" created in "%s"', array($folderName, $targetFolderObject->getIdentifier() . '/'));
704 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException $e) {
705 $this->writelog(6, 1, 103, 'You are not allowed to create directories!', '');
706 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
707 $this->writelog(6, 1, 102, 'Destination path "%s" was not within your mountpoints!', array($targetFolderObject->getIdentifier() . '/'));
708 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException $e) {
709 $this->writelog(6, 1, 101, 'File or directory "%s" existed already!', array($folderName));
710 } catch (\RuntimeException $e) {
711 $this->writelog(6, 1, 100, 'Directory "%s" not created. Write-permission problem in "%s"?', array($folderName, $targetFolderObject->getIdentifier() . '/'));
712 }
713 return $resultObject;
714 }
715
716 /**
717 * This creates a new file. (action=8)
718 * $cmds['data'] (string): The new file name
719 * $cmds['target'] (string): The path where to create it.
720 * + example "2:targetpath/targetfolder/"
721 *
722 * @param array $cmds Command details as described above
723 * @return string Returns the new filename upon success
724 */
725 public function func_newfile($cmds) {
726 if (!$this->isInit) {
727 return FALSE;
728 }
729 $targetFolderObject = $this->getFileObject($cmds['target']);
730 if (!$targetFolderObject instanceof Folder) {
731 $this->writelog(8, 2, 104, 'Destination "%s" was not a directory', array($cmds['target']));
732 return FALSE;
733 }
734 $resultObject = NULL;
735 try {
736 $fileName = $cmds['data'];
737 $resultObject = $targetFolderObject->createFile($fileName);
738 $this->writelog(8, 0, 1, 'File created: "%s"', array($fileName));
739 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
740 $this->writeLog(8, 1, 106, 'Extension of file "%s" was not allowed!', array($fileName));
741 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException $e) {
742 $this->writelog(8, 1, 103, 'You are not allowed to create files!', '');
743 } catch (\TYPO3\CMS\Core\Resource\Exception\NotInMountPointException $e) {
744 $this->writelog(8, 1, 102, 'Destination path "%s" was not within your mountpoints!', array($targetFolderObject->getIdentifier()));
745 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
746 $this->writelog(8, 1, 101, 'File existed already in "%s"!', array($targetFolderObject->getIdentifier()));
747 } catch (\TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException $e) {
748 $this->writelog(8, 1, 106, 'File name "%s" was not allowed!', $fileName);
749 } catch (\RuntimeException $e) {
750 $this->writelog(8, 1, 100, 'File "%s" was not created! Write-permission problem in "%s"?', array($fileName, $targetFolderObject->getIdentifier()));
751 }
752 return $resultObject;
753 }
754
755 /**
756 * Editing textfiles or folders (action=9)
757 *
758 * @param array $cmds $cmds['data'] is the new content. $cmds['target'] is the target (file or dir)
759 * @return bool Returns TRUE on success
760 */
761 public function func_edit($cmds) {
762 if (!$this->isInit) {
763 return FALSE;
764 }
765 // Example indentifier for $cmds['target'] => "4:mypath/tomyfolder/myfile.jpg"
766 // for backwards compatibility: the combined file identifier was the path+filename
767 $fileIdentifier = $cmds['target'];
768 $fileObject = $this->getFileObject($fileIdentifier);
769 // Example indentifier for $cmds['target'] => "2:targetpath/targetfolder/"
770 $content = $cmds['data'];
771 if (!$fileObject instanceof File) {
772 $this->writelog(9, 2, 123, 'Target "%s" was not a file!', array($fileIdentifier));
773 return FALSE;
774 }
775 $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'];
776 if (!GeneralUtility::inList($extList, $fileObject->getExtension())) {
777 $this->writelog(9, 1, 102, 'File extension "%s" is not a textfile format! (%s)', array($fileObject->getExtension(), $extList));
778 return FALSE;
779 }
780 try {
781 $fileObject->setContents($content);
782 clearstatcache();
783 $this->writelog(9, 0, 1, 'File saved to "%s", bytes: %s, MD5: %s ', array($fileObject->getIdentifier(), $fileObject->getSize(), md5($content)));
784 return TRUE;
785 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
786 $this->writelog(9, 1, 104, 'You are not allowed to edit files!', '');
787 return FALSE;
788 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFileWritePermissionsException $e) {
789 $this->writelog(9, 1, 100, 'File "%s" was not saved! Write-permission problem?', array($fileObject->getIdentifier()));
790 return FALSE;
791 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
792 $this->writelog(9, 1, 100, 'File "%s" was not saved! File extension rejected!', array($fileObject->getIdentifier()));
793 return FALSE;
794 }
795 }
796
797 /**
798 * Upload of files (action=1)
799 * when having multiple uploads (HTML5-style), the array $_FILES looks like this:
800 * Array(
801 * [upload_1] => Array(
802 * [name] => Array(
803 * [0] => GData - Content-Elements and Media-Gallery.pdf
804 * [1] => CMS Expo 2011.txt
805 * )
806 * [type] => Array(
807 * [0] => application/pdf
808 * [1] => text/plain
809 * )
810 * [tmp_name] => Array(
811 * [0] => /Applications/MAMP/tmp/php/phpNrOB43
812 * [1] => /Applications/MAMP/tmp/php/phpD2HQAK
813 * )
814 * [size] => Array(
815 * [0] => 373079
816 * [1] => 1291
817 * )
818 * )
819 * )
820 * in HTML you'd need sth like this: <input type="file" name="upload_1[]" multiple="true" />
821 *
822 * @param array $cmds $cmds['data'] is the ID-number (points to the global var that holds the filename-ref ($_FILES['upload_' . $id]['name']) . $cmds['target'] is the target directory, $cmds['charset'] is the the character set of the file name (utf-8 is needed for JS-interaction)
823 * @return File[] | FALSE Returns an array of new file objects upon success. False otherwise
824 */
825 public function func_upload($cmds) {
826 if (!$this->isInit) {
827 return FALSE;
828 }
829 $uploadPosition = $cmds['data'];
830 $uploadedFileData = $_FILES['upload_' . $uploadPosition];
831 if (empty($uploadedFileData['name']) || is_array($uploadedFileData['name']) && empty($uploadedFileData['name'][0])) {
832 $this->writelog(1, 2, 108, 'No file was uploaded!', '');
833 return FALSE;
834 }
835 // Example indentifier for $cmds['target'] => "2:targetpath/targetfolder/"
836 $targetFolderObject = $this->getFileObject($cmds['target']);
837 // Uploading with non HTML-5-style, thus, make an array out of it, so we can loop over it
838 if (!is_array($uploadedFileData['name'])) {
839 $uploadedFileData = array(
840 'name' => array($uploadedFileData['name']),
841 'type' => array($uploadedFileData['type']),
842 'tmp_name' => array($uploadedFileData['tmp_name']),
843 'size' => array($uploadedFileData['size'])
844 );
845 }
846 $resultObjects = array();
847 $numberOfUploadedFilesForPosition = count($uploadedFileData['name']);
848 // Loop through all uploaded files
849 for ($i = 0; $i < $numberOfUploadedFilesForPosition; $i++) {
850 $fileInfo = array(
851 'name' => $uploadedFileData['name'][$i],
852 'type' => $uploadedFileData['type'][$i],
853 'tmp_name' => $uploadedFileData['tmp_name'][$i],
854 'size' => $uploadedFileData['size'][$i]
855 );
856 try {
857 // @todo can be improved towards conflict mode naming
858 if ($this->dontCheckForUnique) {
859 $conflictMode = 'replace';
860 } else {
861 $conflictMode = 'cancel';
862 }
863 /** @var $fileObject File */
864 $fileObject = $targetFolderObject->addUploadedFile($fileInfo, $conflictMode);
865 $fileObject = ResourceFactory::getInstance()->getFileObjectByStorageAndIdentifier($targetFolderObject->getStorage()->getUid(), $fileObject->getIdentifier());
866 if ($conflictMode === 'replace') {
867 $this->getIndexer($fileObject->getStorage())->updateIndexEntry($fileObject);
868 }
869 $resultObjects[] = $fileObject;
870 $this->internalUploadMap[$uploadPosition] = $fileObject->getCombinedIdentifier();
871 $this->writelog(1, 0, 1, 'Uploading file "%s" to "%s"', array($fileInfo['name'], $targetFolderObject->getIdentifier()));
872 } catch (\TYPO3\CMS\Core\Resource\Exception\UploadException $e) {
873 $this->writelog(1, 2, 106, 'The upload has failed, no uploaded file found!', '');
874 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException $e) {
875 $this->writelog(1, 1, 105, 'You are not allowed to upload files!', '');
876 } catch (\TYPO3\CMS\Core\Resource\Exception\UploadSizeException $e) {
877 $this->writelog(1, 1, 104, 'The uploaded file "%s" exceeds the size-limit', array($fileInfo['name']));
878 } catch (\TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException $e) {
879 $this->writelog(1, 1, 103, 'Destination path "%s" was not within your mountpoints!', array($targetFolderObject->getIdentifier()));
880 } catch (\TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException $e) {
881 $this->writelog(1, 1, 102, 'Extension of file name "%s" is not allowed in "%s"!', array($fileInfo['name'], $targetFolderObject->getIdentifier()));
882 } catch (\TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException $e) {
883 $this->writelog(1, 1, 101, 'No unique filename available in "%s"!', array($targetFolderObject->getIdentifier()));
884 } catch (\RuntimeException $e) {
885 $this->writelog(1, 1, 100, 'Uploaded file could not be moved! Write-permission problem in "%s"?', array($targetFolderObject->getIdentifier()));
886 }
887 }
888
889 return $resultObjects;
890 }
891
892 /**
893 * Unzipping file (action=7)
894 * This is permitted only if the user has fullAccess or if the file resides
895 *
896 * @param array $cmds $cmds['data'] is the zip-file. $cmds['target'] is the target directory. If not set we'll default to the same directory as the file is in.
897 * @return bool Returns TRUE on success
898 */
899 public function func_unzip($cmds) {
900 if (!$this->isInit || $this->dont_use_exec_commands) {
901 return FALSE;
902 }
903 $theFile = $cmds['data'];
904 if (!@is_file($theFile)) {
905 $this->writelog(7, 2, 105, 'The file "%s" did not exist!', array($theFile));
906 return FALSE;
907 }
908 $fI = GeneralUtility::split_fileref($theFile);
909 if (!isset($cmds['target'])) {
910 $cmds['target'] = $fI['path'];
911 }
912 // Clean up destination directory
913 // !!! Method has been put in the local driver, can be saftely removed
914 $theDest = $this->is_directory($cmds['target']);
915 if (!$theDest) {
916 $this->writelog(7, 2, 104, 'Destination "%s" was not a directory', array($cmds['target']));
917 return FALSE;
918 }
919 if (!$this->actionPerms['unzipFile']) {
920 $this->writelog(7, 1, 103, 'You are not allowed to unzip files', '');
921 return FALSE;
922 }
923 if ($fI['fileext'] != 'zip') {
924 $this->writelog(7, 1, 102, 'File extension is not "zip"', '');
925 return FALSE;
926 }
927 if (!$this->checkIfFullAccess($theDest)) {
928 $this->writelog(7, 1, 101, 'You don\'t have full access to the destination directory "%s"!', array($theDest));
929 return FALSE;
930 }
931 // !!! Method has been put in the sotrage driver, can be saftely removed
932 if ($this->checkPathAgainstMounts($theFile) && $this->checkPathAgainstMounts($theDest . '/')) {
933 // No way to do this under windows.
934 $cmd = $this->unzipPath . 'unzip -qq ' . escapeshellarg($theFile) . ' -d ' . escapeshellarg($theDest);
935 CommandUtility::exec($cmd);
936 $this->writelog(7, 0, 1, 'Unzipping file "%s" in "%s"', array($theFile, $theDest));
937 return TRUE;
938 } else {
939 $this->writelog(7, 1, 100, 'File "%s" or destination "%s" was not within your mountpoints!', array($theFile, $theDest));
940 return FALSE;
941 }
942 }
943
944 /**
945 * Add flash message to message queue
946 *
947 * @param \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage
948 * @return void
949 */
950 protected function addFlashMessage(FlashMessage $flashMessage) {
951 /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
952 $flashMessageService = GeneralUtility::makeInstance(
953 'TYPO3\\CMS\\Core\\Messaging\\FlashMessageService'
954 );
955 /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
956 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
957 $defaultFlashMessageQueue->enqueue($flashMessage);
958 }
959
960 /**
961 * Gets Indexer
962 *
963 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storage
964 * @return \TYPO3\CMS\Core\Resource\Index\Indexer
965 */
966 protected function getIndexer(ResourceStorage $storage) {
967 return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Index\\Indexer', $storage);
968 }
969
970 /**
971 * Get database connection
972 *
973 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
974 */
975 protected function getDatabaseConnection() {
976 return $GLOBALS['TYPO3_DB'];
977 }
978
979 /**
980 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
981 */
982 protected function getBackendUser() {
983 return $GLOBALS['BE_USER'];
984 }
985
986 }