[BUGFIX] Avoid php8.1 fatal error in FileSessionHandler
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / File / ExtendedFileUtility.php
1 <?php
2
3 /*
4 * This file is part of the TYPO3 CMS project.
5 *
6 * It is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License, either version 2
8 * of the License, or any later version.
9 *
10 * For the full copyright and license information, please read the
11 * LICENSE.txt file that was distributed with this source code.
12 *
13 * The TYPO3 project - inspiring people to share!
14 */
15
16 namespace TYPO3\CMS\Core\Utility\File;
17
18 use Psr\EventDispatcher\EventDispatcherInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Core\Database\Connection;
22 use TYPO3\CMS\Core\Database\ConnectionPool;
23 use TYPO3\CMS\Core\Http\ApplicationType;
24 use TYPO3\CMS\Core\Localization\LanguageService;
25 use TYPO3\CMS\Core\Messaging\FlashMessage;
26 use TYPO3\CMS\Core\Messaging\FlashMessageService;
27 use TYPO3\CMS\Core\Resource\DuplicationBehavior;
28 use TYPO3\CMS\Core\Resource\Event\AfterFileCommandProcessedEvent;
29 use TYPO3\CMS\Core\Resource\Exception;
30 use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException;
31 use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException;
32 use TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException;
33 use TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException;
34 use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException;
35 use TYPO3\CMS\Core\Resource\Exception\InsufficientFileWritePermissionsException;
36 use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException;
37 use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException;
38 use TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException;
39 use TYPO3\CMS\Core\Resource\Exception\InvalidFileException;
40 use TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException;
41 use TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException;
42 use TYPO3\CMS\Core\Resource\Exception\NotInMountPointException;
43 use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
44 use TYPO3\CMS\Core\Resource\Exception\UploadException;
45 use TYPO3\CMS\Core\Resource\Exception\UploadSizeException;
46 use TYPO3\CMS\Core\Resource\File;
47 use TYPO3\CMS\Core\Resource\Folder;
48 use TYPO3\CMS\Core\Resource\Index\Indexer;
49 use TYPO3\CMS\Core\Resource\ResourceFactory;
50 use TYPO3\CMS\Core\Resource\ResourceStorage;
51 use TYPO3\CMS\Core\SysLog\Action\File as SystemLogFileAction;
52 use TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
53 use TYPO3\CMS\Core\SysLog\Type as SystemLogType;
54 use TYPO3\CMS\Core\Type\Exception\InvalidEnumerationValueException;
55 use TYPO3\CMS\Core\Utility\Exception\NotImplementedMethodException;
56 use TYPO3\CMS\Core\Utility\GeneralUtility;
57
58 /**
59 * Contains functions for performing file operations like copying, pasting, uploading, moving,
60 * deleting etc. through the TCE
61 *
62 * See document "TYPO3 Core API" for syntax
63 *
64 * This class contains functions primarily used by tce_file.php (TYPO3 Core Engine for file manipulation)
65 * Functions include copying, moving, deleting, uploading and so on...
66 *
67 * All fileoperations must be within the filemount paths of the user.
68 *
69 * @internal Since TYPO3 v10, this class should not be used anymore outside of TYPO3 Core, and is considered internal,
70 * as the FAL API should be used instead.
71 */
72 class ExtendedFileUtility extends BasicFileUtility
73 {
74 /**
75 * Defines behaviour when uploading files with names that already exist; possible values are
76 * the values of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
77 *
78 * @var \TYPO3\CMS\Core\Resource\DuplicationBehavior
79 */
80 protected $existingFilesConflictMode;
81
82 /**
83 * This array is self-explaining (look in the class below).
84 * It grants access to the functions. This could be set from outside in order to enabled functions to users.
85 * See also the function setActionPermissions() which takes input directly from the user-record
86 *
87 * @var array
88 */
89 public $actionPerms = [
90 // File permissions
91 'addFile' => false,
92 'readFile' => false,
93 'writeFile' => false,
94 'copyFile' => false,
95 'moveFile' => false,
96 'renameFile' => false,
97 'deleteFile' => false,
98 // Folder permissions
99 'addFolder' => false,
100 'readFolder' => false,
101 'writeFolder' => false,
102 'copyFolder' => false,
103 'moveFolder' => false,
104 'renameFolder' => false,
105 'deleteFolder' => false,
106 'recursivedeleteFolder' => false,
107 ];
108
109 /**
110 * Will contain map between upload ID and the final filename
111 *
112 * @var array
113 */
114 public $internalUploadMap = [];
115
116 /**
117 * All error messages from the file operations of this script instance
118 *
119 * @var array
120 */
121 protected $errorMessages = [];
122
123 /**
124 * Container for FlashMessages so they can be localized
125 *
126 * @var array
127 */
128 protected $flashMessages = [];
129
130 /**
131 * @var array
132 */
133 protected $fileCmdMap;
134
135 /**
136 * The File Factory
137 *
138 * @var \TYPO3\CMS\Core\Resource\ResourceFactory
139 */
140 protected $fileFactory;
141
142 /**
143 * Get existingFilesConflictMode
144 *
145 * @return string
146 */
147 public function getExistingFilesConflictMode()
148 {
149 return (string)$this->existingFilesConflictMode;
150 }
151
152 /**
153 * Set existingFilesConflictMode
154 *
155 * @param \TYPO3\CMS\Core\Resource\DuplicationBehavior|string $existingFilesConflictMode Instance or constant of \TYPO3\CMS\Core\Resource\DuplicationBehavior
156 * @throws Exception
157 */
158 public function setExistingFilesConflictMode($existingFilesConflictMode)
159 {
160 try {
161 $this->existingFilesConflictMode = DuplicationBehavior::cast($existingFilesConflictMode);
162 } catch (InvalidEnumerationValueException $e) {
163 throw new Exception(
164 sprintf(
165 'Invalid argument, received: "%s", expected a value from enumeration \TYPO3\CMS\Core\Resource\DuplicationBehavior (%s)',
166 $existingFilesConflictMode,
167 implode(', ', DuplicationBehavior::getConstants())
168 ),
169 1476046229
170 );
171 }
172 }
173
174 /**
175 * Initialization of the class
176 *
177 * @param array $fileCmds Array with the commands to execute. See "TYPO3 Core API" document
178 */
179 public function start($fileCmds)
180 {
181 // Initialize Object Factory
182 $this->fileFactory = GeneralUtility::makeInstance(ResourceFactory::class);
183 // Initializing file processing commands:
184 $this->fileCmdMap = $fileCmds;
185 }
186
187 /**
188 * Sets the file action permissions.
189 * If no argument is given, permissions of the currently logged in backend user are taken into account.
190 *
191 * @param array $permissions File Permissions.
192 */
193 public function setActionPermissions(array $permissions = [])
194 {
195 if (empty($permissions)) {
196 $permissions = $this->getBackendUser()->getFilePermissions();
197 }
198 $this->actionPerms = $permissions;
199 }
200
201 /**
202 * Processing the command array in $this->fileCmdMap
203 *
204 * @return mixed FALSE, if the file functions were not initialized
205 * @throws \UnexpectedValueException
206 */
207 public function processData()
208 {
209 $result = [];
210 if (is_array($this->fileCmdMap)) {
211 // Check if there were uploads expected, but no one made
212 if ($this->fileCmdMap['upload'] ?? false) {
213 $uploads = $this->fileCmdMap['upload'];
214 foreach ($uploads as $upload) {
215 if (empty($_FILES['upload_' . $upload['data']]['name'])
216 || (
217 is_array($_FILES['upload_' . $upload['data']]['name'])
218 && empty($_FILES['upload_' . $upload['data']]['name'][0])
219 )
220 ) {
221 unset($this->fileCmdMap['upload'][$upload['data']]);
222 }
223 }
224 if (empty($this->fileCmdMap['upload'])) {
225 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 108, 'No file was uploaded!', []);
226 $this->addMessageToFlashMessageQueue('FileUtility.NoFileWasUploaded');
227 }
228 }
229
230 // Check if there were new folder names expected, but non given
231 if ($this->fileCmdMap['newfolder'] ?? false) {
232 foreach ($this->fileCmdMap['newfolder'] as $key => $cmdArr) {
233 if (empty($cmdArr['data'])) {
234 unset($this->fileCmdMap['newfolder'][$key]);
235 }
236 }
237 if (empty($this->fileCmdMap['newfolder'])) {
238 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::USER_ERROR, 108, 'No name for new folder given!', []);
239 $this->addMessageToFlashMessageQueue('FileUtility.NoNameForNewFolderGiven');
240 }
241 }
242
243 // Traverse each set of actions
244 foreach ($this->fileCmdMap as $action => $actionData) {
245 // Traverse all action data. More than one file might be affected at the same time.
246 if (is_array($actionData)) {
247 $result[$action] = [];
248 // We reset the array keys of $actionData to keep track of the corresponding
249 // result, while not changing the previous behaviour of $result[$action][].
250 foreach (array_values($actionData) as $key => $cmdArr) {
251 // Clear file stats
252 clearstatcache();
253 // Branch out based on command:
254 switch ($action) {
255 case 'delete':
256 $result[$action][$key] = $this->func_delete($cmdArr);
257 break;
258 case 'copy':
259 $result[$action][$key] = $this->func_copy($cmdArr);
260 break;
261 case 'move':
262 $result[$action][$key] = $this->func_move($cmdArr);
263 break;
264 case 'rename':
265 $result[$action][$key] = $this->func_rename($cmdArr);
266 break;
267 case 'newfolder':
268 $result[$action][$key] = $this->func_newfolder($cmdArr);
269 break;
270 case 'newfile':
271 $result[$action][$key] = $this->func_newfile($cmdArr);
272 break;
273 case 'editfile':
274 $result[$action][$key] = $this->func_edit($cmdArr);
275 break;
276 case 'upload':
277 $result[$action][$key] = $this->func_upload($cmdArr);
278 break;
279 case 'replace':
280 $result[$action][$key] = $this->replaceFile($cmdArr);
281 break;
282 }
283
284 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'])) {
285 trigger_error(
286 'The hook $TYPO3_CONF_VARS[SC_OPTIONS][t3lib/class.t3lib_extfilefunc.php][processData] is deprecated and will stop working in TYPO3 v12.0. Use the AfterFileCommandProcessedEvent instead.',
287 E_USER_DEPRECATED
288 );
289 }
290
291 // Hook for post-processing the action
292 // @deprecated will be removed in TYPO3 v12.0.
293 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'] ?? [] as $className) {
294 $hookObject = GeneralUtility::makeInstance($className);
295 if (!$hookObject instanceof ExtendedFileUtilityProcessDataHookInterface) {
296 throw new \UnexpectedValueException($className . ' must implement interface ' . ExtendedFileUtilityProcessDataHookInterface::class, 1279719168);
297 }
298 $hookObject->processData_postProcessAction($action, $cmdArr, $result[$action], $this);
299 }
300
301 GeneralUtility::getContainer()->get(EventDispatcherInterface::class)->dispatch(
302 new AfterFileCommandProcessedEvent([$action => $cmdArr], $result[$action][$key], (string)$this->existingFilesConflictMode)
303 );
304 }
305 }
306 }
307 }
308 return $result;
309 }
310
311 /**
312 * Return all error messages from the file operations of this script instance
313 *
314 * @return array all errorMessages as a numerical array
315 */
316 public function getErrorMessages()
317 {
318 return $this->errorMessages;
319 }
320
321 /**
322 * @param int $action The action number. See the functions in the class for a hint. Eg. edit is '9', upload is '1' ...
323 * @param int $error The severity: 0 = message, 1 = error, 2 = System Error, 3 = security notice (admin)
324 * @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.
325 * @param string $details This is the default, raw error message in english
326 * @param array $data Array with special information that may go into $details by "%s" marks / sprintf() when the log is shown
327 */
328 public function writeLog($action, $error, $details_nr, $details, $data)
329 {
330 if (is_object($this->getBackendUser())) {
331 $this->getBackendUser()->writelog(SystemLogType::FILE, $action, $error, $details_nr, $details, $data);
332 }
333 if ($error > 0) {
334 $this->errorMessages[] = vsprintf($details, $data);
335 }
336 }
337
338 /**
339 * Adds a localized FlashMessage to the message queue
340 *
341 * @param string $localizationKey
342 * @param array $replaceMarkers
343 * @param int $severity
344 * @throws \InvalidArgumentException
345 */
346 protected function addMessageToFlashMessageQueue($localizationKey, array $replaceMarkers = [], $severity = FlashMessage::ERROR)
347 {
348 if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
349 && ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()
350 ) {
351 $label = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/fileMessages.xlf:' . $localizationKey);
352 $message = vsprintf($label, $replaceMarkers);
353 $flashMessage = GeneralUtility::makeInstance(
354 FlashMessage::class,
355 $message,
356 '',
357 $severity,
358 true
359 );
360 $this->addFlashMessage($flashMessage);
361 }
362 }
363
364 /*************************************
365 *
366 * File operation functions
367 *
368 **************************************/
369 /**
370 * Deleting files and folders (action=4)
371 *
372 * @param array $cmds $cmds['data'] is the file/folder to delete
373 * @return bool Returns TRUE upon success
374 */
375 public function func_delete(array $cmds)
376 {
377 $result = false;
378 // Example identifier for $cmds['data'] => "4:mypath/tomyfolder/myfile.jpg"
379 // for backwards compatibility: the combined file identifier was the path+filename
380 try {
381 $fileObject = $this->getFileObject($cmds['data']);
382 } catch (ResourceDoesNotExistException $e) {
383 $flashMessage = GeneralUtility::makeInstance(
384 FlashMessage::class,
385 sprintf(
386 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.description.fileNotFound'),
387 $cmds['data']
388 ),
389 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.header.fileNotFound'),
390 FlashMessage::ERROR,
391 true
392 );
393 $this->addFlashMessage($flashMessage);
394
395 return false;
396 }
397 // checks to delete the file
398 if ($fileObject instanceof File) {
399 // check if the file still has references
400 // Exclude sys_file_metadata records as these are no use references
401 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
402 $refIndexRecords = $queryBuilder
403 ->select('tablename', 'recuid', 'ref_uid')
404 ->from('sys_refindex')
405 ->where(
406 $queryBuilder->expr()->eq(
407 'ref_table',
408 $queryBuilder->createNamedParameter('sys_file', \PDO::PARAM_STR)
409 ),
410 $queryBuilder->expr()->eq(
411 'ref_uid',
412 $queryBuilder->createNamedParameter($fileObject->getUid(), \PDO::PARAM_INT)
413 ),
414 $queryBuilder->expr()->neq(
415 'tablename',
416 $queryBuilder->createNamedParameter('sys_file_metadata', \PDO::PARAM_STR)
417 )
418 )
419 ->execute()
420 ->fetchAllAssociative();
421 $deleteFile = true;
422 if (!empty($refIndexRecords)) {
423 $shortcutContent = [];
424 $brokenReferences = [];
425
426 foreach ($refIndexRecords as $fileReferenceRow) {
427 if ($fileReferenceRow['tablename'] === 'sys_file_reference') {
428 $row = $this->transformFileReferenceToRecordReference($fileReferenceRow);
429 $shortcutRecord = BackendUtility::getRecord($row['tablename'], $row['recuid']);
430
431 if ($shortcutRecord) {
432 $shortcutContent[] = '[record:' . $row['tablename'] . ':' . $row['recuid'] . ']';
433 } else {
434 $brokenReferences[] = $fileReferenceRow['ref_uid'];
435 }
436 } else {
437 $shortcutContent[] = '[record:' . $fileReferenceRow['tablename'] . ':' . $fileReferenceRow['recuid'] . ']';
438 }
439 }
440 if (!empty($brokenReferences)) {
441 // render a message that the file has broken references
442 $flashMessage = GeneralUtility::makeInstance(
443 FlashMessage::class,
444 sprintf($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.description.fileHasBrokenReferences'), count($brokenReferences)),
445 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.header.fileHasBrokenReferences'),
446 FlashMessage::INFO,
447 true
448 );
449 $this->addFlashMessage($flashMessage);
450 }
451 if (!empty($shortcutContent)) {
452 // render a message that the file could not be deleted
453 $flashMessage = GeneralUtility::makeInstance(
454 FlashMessage::class,
455 sprintf($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.description.fileNotDeletedHasReferences'), $fileObject->getName()) . ' ' . implode(', ', $shortcutContent),
456 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.header.fileNotDeletedHasReferences'),
457 FlashMessage::WARNING,
458 true
459 );
460 $this->addFlashMessage($flashMessage);
461 $deleteFile = false;
462 }
463 }
464
465 if ($deleteFile) {
466 try {
467 $result = $fileObject->delete();
468
469 // show the user that the file was deleted
470 $flashMessage = GeneralUtility::makeInstance(
471 FlashMessage::class,
472 sprintf($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.description.fileDeleted'), $fileObject->getName()),
473 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.header.fileDeleted'),
474 FlashMessage::OK,
475 true
476 );
477 $this->addFlashMessage($flashMessage);
478 // Log success
479 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::MESSAGE, 1, 'File "%s" deleted', [$fileObject->getIdentifier()]);
480 } catch (InsufficientFileAccessPermissionsException $e) {
481 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 112, 'You are not allowed to access the file', [$fileObject->getIdentifier()]);
482 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToAccessTheFile', [$fileObject->getIdentifier()]);
483 } catch (NotInMountPointException $e) {
484 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 111, 'Target was not within your mountpoints! T="%s"', [$fileObject->getIdentifier()]);
485 $this->addMessageToFlashMessageQueue('FileUtility.TargetWasNotWithinYourMountpoints', [$fileObject->getIdentifier()]);
486 } catch (\RuntimeException $e) {
487 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 110, 'Could not delete file "%s". Write-permission problem?', [$fileObject->getIdentifier()]);
488 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotDeleteFile', [$fileObject->getIdentifier()]);
489 }
490 }
491 } else {
492 /** @var Folder $fileObject */
493 if (!$this->folderHasFilesInUse($fileObject)) {
494 try {
495 $result = $fileObject->delete(true);
496 if ($result) {
497 // notify the user that the folder was deleted
498 /** @var FlashMessage $flashMessage */
499 $flashMessage = GeneralUtility::makeInstance(
500 FlashMessage::class,
501 sprintf($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.description.folderDeleted'), $fileObject->getName()),
502 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.header.folderDeleted'),
503 FlashMessage::OK,
504 true
505 );
506 $this->addFlashMessage($flashMessage);
507 // Log success
508 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::MESSAGE, 3, 'Directory "%s" deleted', [$fileObject->getIdentifier()]);
509 }
510 } catch (InsufficientUserPermissionsException $e) {
511 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 120, 'Could not delete directory! Is directory "%s" empty? (You are not allowed to delete directories recursively).', [$fileObject->getIdentifier()]);
512 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotDeleteDirectory', [$fileObject->getIdentifier()]);
513 } catch (InsufficientFolderAccessPermissionsException $e) {
514 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 123, 'You are not allowed to access the directory', [$fileObject->getIdentifier()]);
515 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToAccessTheDirectory', [$fileObject->getIdentifier()]);
516 } catch (NotInMountPointException $e) {
517 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 121, 'Target was not within your mountpoints! T="%s"', [$fileObject->getIdentifier()]);
518 $this->addMessageToFlashMessageQueue('FileUtility.TargetWasNotWithinYourMountpoints', [$fileObject->getIdentifier()]);
519 } catch (FileOperationErrorException $e) {
520 $this->writeLog(SystemLogFileAction::DELETE, SystemLogErrorClassification::USER_ERROR, 120, 'Could not delete directory "%s"! Write-permission problem?', [$fileObject->getIdentifier()]);
521 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotDeleteDirectory', [$fileObject->getIdentifier()]);
522 }
523 }
524 }
525
526 return $result;
527 }
528
529 /**
530 * Checks files in given folder recursively for for existing references.
531 *
532 * Creates a flash message if there are references.
533 *
534 * @param Folder $folder
535 * @return bool TRUE if folder has files in use, FALSE otherwise
536 */
537 public function folderHasFilesInUse(Folder $folder)
538 {
539 $files = $folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, true);
540 if (empty($files)) {
541 return false;
542 }
543
544 /** @var int[] $fileUids */
545 $fileUids = [];
546 foreach ($files as $file) {
547 $fileUids[] = $file->getUid();
548 }
549
550 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
551 $numberOfReferences = $queryBuilder
552 ->count('hash')
553 ->from('sys_refindex')
554 ->where(
555 $queryBuilder->expr()->eq(
556 'ref_table',
557 $queryBuilder->createNamedParameter('sys_file', \PDO::PARAM_STR)
558 ),
559 $queryBuilder->expr()->in(
560 'ref_uid',
561 $queryBuilder->createNamedParameter($fileUids, Connection::PARAM_INT_ARRAY)
562 ),
563 $queryBuilder->expr()->neq(
564 'tablename',
565 $queryBuilder->createNamedParameter('sys_file_metadata', \PDO::PARAM_STR)
566 )
567 )->execute()->fetchOne();
568
569 $hasReferences = $numberOfReferences > 0;
570 if ($hasReferences) {
571 /** @var FlashMessage $flashMessage */
572 $flashMessage = GeneralUtility::makeInstance(
573 FlashMessage::class,
574 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.description.folderNotDeletedHasFilesWithReferences'),
575 $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:message.header.folderNotDeletedHasFilesWithReferences'),
576 FlashMessage::WARNING,
577 true
578 );
579 $this->addFlashMessage($flashMessage);
580 }
581
582 return $hasReferences;
583 }
584
585 /**
586 * Maps results from the fal file reference table on the
587 * structure of the normal reference index table.
588 *
589 * @param array $referenceRecord
590 * @return array
591 */
592 protected function transformFileReferenceToRecordReference(array $referenceRecord)
593 {
594 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
595 $queryBuilder->getRestrictions()->removeAll();
596 $fileReference = $queryBuilder
597 ->select('uid_foreign', 'tablenames', 'fieldname', 'sorting_foreign')
598 ->from('sys_file_reference')
599 ->where(
600 $queryBuilder->expr()->eq(
601 'uid',
602 $queryBuilder->createNamedParameter($referenceRecord['recuid'], \PDO::PARAM_INT)
603 )
604 )
605 ->execute()
606 ->fetchAssociative();
607
608 return [
609 'recuid' => $fileReference['uid_foreign'],
610 'tablename' => $fileReference['tablenames'],
611 'field' => $fileReference['fieldname'],
612 'flexpointer' => '',
613 'softref_key' => '',
614 'sorting' => $fileReference['sorting_foreign'],
615 ];
616 }
617
618 /**
619 * Gets a File or a Folder object from an identifier [storage]:[fileId]
620 *
621 * @param string $identifier
622 * @return File|Folder
623 * @throws Exception\InsufficientFileAccessPermissionsException
624 * @throws Exception\InvalidFileException
625 */
626 protected function getFileObject($identifier)
627 {
628 $object = $this->fileFactory->retrieveFileOrFolderObject($identifier);
629 if (!is_object($object)) {
630 throw new InvalidFileException('The item ' . $identifier . ' was not a file or directory!!', 1320122453);
631 }
632 if ($object->getStorage()->getUid() === 0) {
633 throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1375889830);
634 }
635 return $object;
636 }
637
638 /**
639 * Copying files and folders (action=2)
640 *
641 * $cmds['data'] (string): The file/folder to copy
642 * + example "4:mypath/tomyfolder/myfile.jpg")
643 * + for backwards compatibility: the identifier was the path+filename
644 * $cmds['target'] (string): The path where to copy to.
645 * + example "2:targetpath/targetfolder/"
646 * $cmds['altName'] (string): Use an alternative name if the target already exists
647 *
648 * @param array $cmds Command details as described above
649 * @return \TYPO3\CMS\Core\Resource\File|false
650 */
651 protected function func_copy($cmds)
652 {
653 $sourceFileObject = $this->getFileObject($cmds['data']);
654 /** @var \TYPO3\CMS\Core\Resource\Folder $targetFolderObject */
655 $targetFolderObject = $this->getFileObject($cmds['target']);
656 // Basic check
657 if (!$targetFolderObject instanceof Folder) {
658 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::SYSTEM_ERROR, 100, 'Destination "%s" was not a directory', [$cmds['target']]);
659 $this->addMessageToFlashMessageQueue('FileUtility.DestinationWasNotADirectory', [$cmds['target']]);
660 return false;
661 }
662 // If this is TRUE, we append _XX to the file name if
663 $appendSuffixOnConflict = (string)($cmds['altName'] ?? '');
664 $resultObject = null;
665 $conflictMode = $appendSuffixOnConflict !== '' ? DuplicationBehavior::RENAME : DuplicationBehavior::CANCEL;
666 // Copying the file
667 if ($sourceFileObject instanceof File) {
668 try {
669 $resultObject = $sourceFileObject->copyTo($targetFolderObject, null, $conflictMode);
670 } catch (InsufficientUserPermissionsException $e) {
671 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 114, 'You are not allowed to copy files', []);
672 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToCopyFiles');
673 } catch (InsufficientFileAccessPermissionsException $e) {
674 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
675 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotAccessAllNecessaryResources', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
676 } catch (IllegalFileExtensionException $e) {
677 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 111, 'Extension of file name "%s" is not allowed in "%s"!', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
678 $this->addMessageToFlashMessageQueue('FileUtility.ExtensionOfFileNameIsNotAllowedIn', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
679 } catch (ExistingTargetFileNameException $e) {
680 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 112, 'File "%s" already exists in folder "%s"!', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
681 $this->addMessageToFlashMessageQueue('FileUtility.FileAlreadyExistsInFolder', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
682 } catch (NotImplementedMethodException $e) {
683 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 128, 'The function to copy a file between storages is not yet implemented', []);
684 $this->addMessageToFlashMessageQueue('FileUtility.TheFunctionToCopyAFileBetweenStoragesIsNotYetImplemented');
685 } catch (\RuntimeException $e) {
686 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::SYSTEM_ERROR, 109, 'File "%s" WAS NOT copied to "%s"! Write-permission problem?', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
687 $this->addMessageToFlashMessageQueue('FileUtility.FileWasNotCopiedTo', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
688 }
689 if ($resultObject) {
690 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::MESSAGE, 1, 'File "%s" copied to "%s"', [$sourceFileObject->getIdentifier(), $resultObject->getIdentifier()]);
691 $this->addMessageToFlashMessageQueue('FileUtility.FileCopiedTo', [$sourceFileObject->getIdentifier(), $resultObject->getIdentifier()], FlashMessage::OK);
692 }
693 } else {
694 // Else means this is a Folder
695 $sourceFolderObject = $sourceFileObject;
696 try {
697 $resultObject = $sourceFolderObject->copyTo($targetFolderObject, null, $conflictMode);
698 } catch (InsufficientUserPermissionsException $e) {
699 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 125, 'You are not allowed to copy directories', []);
700 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToCopyDirectories');
701 } catch (InsufficientFileAccessPermissionsException $e) {
702 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
703 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotAccessAllNecessaryResources', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
704 } catch (InsufficientFolderAccessPermissionsException $e) {
705 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 121, 'You don\'t have full access to the destination directory "%s"!', [$targetFolderObject->getIdentifier()]);
706 $this->addMessageToFlashMessageQueue('FileUtility.YouDontHaveFullAccessToTheDestinationDirectory', [$targetFolderObject->getIdentifier()]);
707 } catch (InvalidTargetFolderException $e) {
708 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 122, 'Cannot copy folder "%s" into target folder "%s", because there is already a folder or file with that name in the target folder!', [$sourceFolderObject->getName(), $targetFolderObject->getName()]);
709 $this->addMessageToFlashMessageQueue('FileUtility.CannotCopyFolderIntoTargetFolderBecauseTheTargetFolderIsAlreadyWithinTheFolderToBeCopied', [$sourceFolderObject->getName(), $targetFolderObject->getIdentifier()]);
710 } catch (ExistingTargetFolderException $e) {
711 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::USER_ERROR, 123, 'Target "%s" already exists!', [$targetFolderObject->getIdentifier()]);
712 $this->addMessageToFlashMessageQueue('FileUtility.TargetAlreadyExists', [$targetFolderObject->getIdentifier()]);
713 } catch (NotImplementedMethodException $e) {
714 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 129, 'The function to copy a folder between storages is not yet implemented', []);
715 $this->addMessageToFlashMessageQueue('FileUtility.TheFunctionToCopyAFolderBetweenStoragesIsNotYetImplemented');
716 } catch (\RuntimeException $e) {
717 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::SYSTEM_ERROR, 119, 'Directory "%s" WAS NOT copied to "%s"! Write-permission problem?', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
718 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryWasNotCopiedTo', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
719 }
720 if ($resultObject) {
721 $this->writeLog(SystemLogFileAction::COPY, SystemLogErrorClassification::MESSAGE, 2, 'Directory "%s" copied to "%s"', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
722 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryCopiedTo', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()], FlashMessage::OK);
723 }
724 }
725 return $resultObject;
726 }
727
728 /**
729 * Moving files and folders (action=3)
730 *
731 * $cmds['data'] (string): The file/folder to move
732 * + example "4:mypath/tomyfolder/myfile.jpg")
733 * + for backwards compatibility: the identifier was the path+filename
734 * $cmds['target'] (string): The path where to move to.
735 * + example "2:targetpath/targetfolder/"
736 * $cmds['altName'] (string): Use an alternative name if the target already exists
737 *
738 * @param array $cmds Command details as described above
739 * @return \TYPO3\CMS\Core\Resource\File|false
740 */
741 protected function func_move($cmds)
742 {
743 $sourceFileObject = $this->getFileObject($cmds['data']);
744 $targetFolderObject = $this->getFileObject($cmds['target']);
745 // Basic check
746 if (!$targetFolderObject instanceof Folder) {
747 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::SYSTEM_ERROR, 100, 'Destination "%s" was not a directory', [$cmds['target']]);
748 $this->addMessageToFlashMessageQueue('FileUtility.DestinationWasNotADirectory', [$cmds['target']]);
749 return false;
750 }
751 $alternativeName = (string)($cmds['altName'] ?? '');
752 $resultObject = null;
753 // Moving the file
754 if ($sourceFileObject instanceof File) {
755 try {
756 if ($alternativeName !== '') {
757 // Don't allow overwriting existing files, but find a new name
758 $resultObject = $sourceFileObject->moveTo($targetFolderObject, $alternativeName, DuplicationBehavior::RENAME);
759 } else {
760 // Don't allow overwriting existing files
761 $resultObject = $sourceFileObject->moveTo($targetFolderObject, null, DuplicationBehavior::CANCEL);
762 }
763 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::MESSAGE, 1, 'File "%s" moved to "%s"', [$sourceFileObject->getIdentifier(), $resultObject->getIdentifier()]);
764 $this->addMessageToFlashMessageQueue('FileUtility.FileMovedTo', [$sourceFileObject->getIdentifier(), $resultObject->getIdentifier()], FlashMessage::OK);
765 } catch (InsufficientUserPermissionsException $e) {
766 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 114, 'You are not allowed to move files', []);
767 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToMoveFiles');
768 } catch (InsufficientFileAccessPermissionsException $e) {
769 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
770 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotAccessAllNecessaryResources', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
771 } catch (IllegalFileExtensionException $e) {
772 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 111, 'Extension of file name "%s" is not allowed in "%s"!', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
773 $this->addMessageToFlashMessageQueue('FileUtility.ExtensionOfFileNameIsNotAllowedIn', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
774 } catch (ExistingTargetFileNameException $e) {
775 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 112, 'File "%s" already exists in folder "%s"!', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
776 $this->addMessageToFlashMessageQueue('FileUtility.FileAlreadyExistsInFolder', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
777 } catch (NotImplementedMethodException $e) {
778 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 126, 'The function to move a file between storages is not yet implemented', []);
779 $this->addMessageToFlashMessageQueue('FileUtility.TheFunctionToMoveAFileBetweenStoragesIsNotYetImplemented');
780 } catch (\RuntimeException $e) {
781 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::SYSTEM_ERROR, 109, 'File "%s" WAS NOT copied to "%s"! Write-permission problem?', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
782 $this->addMessageToFlashMessageQueue('FileUtility.FileWasNotCopiedTo', [$sourceFileObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
783 }
784 } else {
785 // Else means this is a Folder
786 $sourceFolderObject = $sourceFileObject;
787 try {
788 if ($alternativeName !== '') {
789 // Don't allow overwriting existing files, but find a new name
790 $resultObject = $sourceFolderObject->moveTo($targetFolderObject, $alternativeName, DuplicationBehavior::RENAME);
791 } else {
792 // Don't allow overwriting existing files
793 $resultObject = $sourceFolderObject->moveTo($targetFolderObject, null, DuplicationBehavior::RENAME);
794 }
795 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::MESSAGE, 2, 'Directory "%s" moved to "%s"', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
796 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryMovedTo', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()], FlashMessage::OK);
797 } catch (InsufficientUserPermissionsException $e) {
798 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 125, 'You are not allowed to move directories', []);
799 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToMoveDirectories');
800 } catch (InsufficientFileAccessPermissionsException $e) {
801 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 110, 'Could not access all necessary resources. Source file or destination maybe was not within your mountpoints? T="%s", D="%s"', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
802 $this->addMessageToFlashMessageQueue('FileUtility.CouldNotAccessAllNecessaryResources', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
803 } catch (InsufficientFolderAccessPermissionsException $e) {
804 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 121, 'You don\'t have full access to the destination directory "%s"!', [$targetFolderObject->getIdentifier()]);
805 $this->addMessageToFlashMessageQueue('FileUtility.YouDontHaveFullAccessToTheDestinationDirectory', [$targetFolderObject->getIdentifier()]);
806 } catch (InvalidTargetFolderException $e) {
807 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 122, 'Cannot move folder "%s" into target folder "%s", because the target folder is already within the folder to be moved!', [$sourceFolderObject->getName(), $targetFolderObject->getName()]);
808 $this->addMessageToFlashMessageQueue('FileUtility.CannotMoveFolderIntoTargetFolderBecauseTheTargetFolderIsAlreadyWithinTheFolderToBeMoved', [$sourceFolderObject->getName(), $targetFolderObject->getName()]);
809 } catch (ExistingTargetFolderException $e) {
810 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 123, 'Target "%s" already exists!', [$targetFolderObject->getIdentifier()]);
811 $this->addMessageToFlashMessageQueue('FileUtility.TargetAlreadyExists', [$targetFolderObject->getIdentifier()]);
812 } catch (NotImplementedMethodException $e) {
813 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::USER_ERROR, 127, 'The function to move a folder between storages is not yet implemented', []);
814 $this->addMessageToFlashMessageQueue('FileUtility.TheFunctionToMoveAFolderBetweenStoragesIsNotYetImplemented', []);
815 } catch (\RuntimeException $e) {
816 $this->writeLog(SystemLogFileAction::MOVE, SystemLogErrorClassification::SYSTEM_ERROR, 119, 'Directory "%s" WAS NOT moved to "%s"! Write-permission problem?', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
817 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryWasNotMovedTo', [$sourceFolderObject->getIdentifier(), $targetFolderObject->getIdentifier()]);
818 }
819 }
820 return $resultObject;
821 }
822
823 /**
824 * Renaming files or folders (action=5)
825 *
826 * $cmds['data'] (string): The file/folder to copy
827 * + example "4:mypath/tomyfolder/myfile.jpg")
828 * + for backwards compatibility: the identifier was the path+filename
829 * $cmds['target'] (string): New name of the file/folder
830 *
831 * @param array $cmds Command details as described above
832 * @return \TYPO3\CMS\Core\Resource\File Returns the new file upon success
833 */
834 public function func_rename($cmds)
835 {
836 $sourceFileObject = $this->getFileObject($cmds['data']);
837 $sourceFile = $sourceFileObject->getName();
838 $targetFile = $cmds['target'];
839 $resultObject = null;
840 if ($sourceFileObject instanceof File) {
841 try {
842 // Try to rename the File
843 $resultObject = $sourceFileObject->rename($targetFile, $this->existingFilesConflictMode);
844 if ($resultObject->getName() !== $targetFile) {
845 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 1, 'File renamed from "%s" to "%s". Filename had to be sanitized!', [$sourceFile, $targetFile]);
846 $this->addMessageToFlashMessageQueue('FileUtility.FileNameSanitized', [$targetFile, $resultObject->getName()], FlashMessage::WARNING);
847 } else {
848 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::MESSAGE, 1, 'File renamed from "%s" to "%s"', [$sourceFile, $targetFile]);
849 }
850 if ($sourceFile === $resultObject->getName()) {
851 $this->addMessageToFlashMessageQueue('FileUtility.FileRenamedSameName', [$sourceFile], FlashMessage::INFO);
852 } else {
853 $this->addMessageToFlashMessageQueue('FileUtility.FileRenamedFromTo', [$sourceFile, $resultObject->getName()], FlashMessage::OK);
854 }
855 } catch (InsufficientUserPermissionsException $e) {
856 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 102, 'You are not allowed to rename files!', []);
857 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToRenameFiles');
858 } catch (IllegalFileExtensionException $e) {
859 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 101, 'Extension of file name "%s" or "%s" was not allowed!', [$sourceFileObject->getName(), $targetFile]);
860 $this->addMessageToFlashMessageQueue('FileUtility.ExtensionOfFileNameOrWasNotAllowed', [$sourceFileObject->getName(), $targetFile]);
861 } catch (ExistingTargetFileNameException $e) {
862 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 120, 'Destination "%s" existed already!', [$targetFile]);
863 $this->addMessageToFlashMessageQueue('FileUtility.DestinationExistedAlready', [$targetFile]);
864 } catch (NotInMountPointException $e) {
865 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 121, 'Destination path "%s" was not within your mountpoints!', [$targetFile]);
866 $this->addMessageToFlashMessageQueue('FileUtility.DestinationPathWasNotWithinYourMountpoints', [$targetFile]);
867 } catch (\RuntimeException $e) {
868 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 100, 'File "%s" was not renamed! Write-permission problem in "%s"?', [$sourceFileObject->getName(), $targetFile]);
869 $this->addMessageToFlashMessageQueue('FileUtility.FileWasNotRenamed', [$sourceFileObject->getName(), $targetFile]);
870 }
871 } else {
872 // Else means this is a Folder
873 try {
874 // Try to rename the Folder
875 $resultObject = $sourceFileObject->rename($targetFile);
876 $newFolderName = $resultObject->getName();
877 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::MESSAGE, 2, 'Directory renamed from "%s" to "%s"', [$sourceFile, $targetFile]);
878 if ($sourceFile === $newFolderName) {
879 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryRenamedSameName', [$sourceFile], FlashMessage::INFO);
880 } else {
881 if ($newFolderName === $targetFile) {
882 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryRenamedFromTo', [$sourceFile, $newFolderName], FlashMessage::OK);
883 } else {
884 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryRenamedFromToCharReplaced', [$sourceFile, $newFolderName], FlashMessage::WARNING);
885 }
886 }
887 } catch (InsufficientUserPermissionsException $e) {
888 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 111, 'You are not allowed to rename directories!', []);
889 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToRenameDirectories');
890 } catch (ExistingTargetFileNameException $e) {
891 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 120, 'Destination "%s" existed already!', [$targetFile]);
892 $this->addMessageToFlashMessageQueue('FileUtility.DestinationExistedAlready', [$targetFile]);
893 } catch (NotInMountPointException $e) {
894 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 121, 'Destination path "%s" was not within your mountpoints!', [$targetFile]);
895 $this->addMessageToFlashMessageQueue('FileUtility.DestinationPathWasNotWithinYourMountpoints', [$targetFile]);
896 } catch (\RuntimeException $e) {
897 $this->writeLog(SystemLogFileAction::RENAME, SystemLogErrorClassification::USER_ERROR, 110, 'Directory "%s" was not renamed! Write-permission problem in "%s"?', [$sourceFileObject->getName(), $targetFile]);
898 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryWasNotRenamed', [$sourceFileObject->getName(), $targetFile]);
899 }
900 }
901 return $resultObject;
902 }
903
904 /**
905 * This creates a new folder. (action=6)
906 *
907 * $cmds['data'] (string): The new folder name
908 * $cmds['target'] (string): The path where to copy to.
909 * + example "2:targetpath/targetfolder/"
910 *
911 * @param array $cmds Command details as described above
912 * @return \TYPO3\CMS\Core\Resource\Folder|false Returns the new foldername upon success
913 */
914 public function func_newfolder($cmds)
915 {
916 $resultObject = false;
917 $targetFolderObject = $this->getFileObject($cmds['target']);
918 if (!$targetFolderObject instanceof Folder) {
919 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::SYSTEM_ERROR, 104, 'Destination "%s" was not a directory', [$cmds['target']]);
920 $this->addMessageToFlashMessageQueue('FileUtility.DestinationWasNotADirectory', [$cmds['target']]);
921 return false;
922 }
923 $folderName = $cmds['data'];
924 try {
925 $resultObject = $targetFolderObject->createFolder($folderName);
926 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::MESSAGE, 1, 'Directory "%s" created in "%s"', [$folderName, $targetFolderObject->getIdentifier()]);
927 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryCreatedIn', [$folderName, $targetFolderObject->getIdentifier()], FlashMessage::OK);
928 } catch (InvalidFileNameException $e) {
929 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::USER_ERROR, 104, 'Invalid folder name "%s"!', [$folderName]);
930 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToCreateDirectories', [$folderName]);
931 } catch (InsufficientFolderWritePermissionsException $e) {
932 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::USER_ERROR, 103, 'You are not allowed to create directories!', []);
933 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToCreateDirectories');
934 } catch (NotInMountPointException $e) {
935 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::USER_ERROR, 102, 'Destination path "%s" was not within your mountpoints!', [$targetFolderObject->getIdentifier()]);
936 $this->addMessageToFlashMessageQueue('FileUtility.DestinationPathWasNotWithinYourMountpoints', [$targetFolderObject->getIdentifier()]);
937 } catch (ExistingTargetFolderException $e) {
938 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::USER_ERROR, 101, 'File or directory "%s" existed already!', [$folderName]);
939 $this->addMessageToFlashMessageQueue('FileUtility.FileOrDirectoryExistedAlready', [$folderName]);
940 } catch (\RuntimeException $e) {
941 $this->writeLog(SystemLogFileAction::NEW_FOLDER, SystemLogErrorClassification::USER_ERROR, 100, 'Directory "%s" not created. Write-permission problem in "%s"?', [$folderName, $targetFolderObject->getIdentifier()]);
942 $this->addMessageToFlashMessageQueue('FileUtility.DirectoryNotCreated', [$folderName, $targetFolderObject->getIdentifier()]);
943 }
944 return $resultObject;
945 }
946
947 /**
948 * This creates a new file. (action=8)
949 * $cmds['data'] (string): The new file name
950 * $cmds['target'] (string): The path where to create it.
951 * + example "2:targetpath/targetfolder/"
952 *
953 * @param array $cmds Command details as described above
954 * @return string Returns the new filename upon success
955 */
956 public function func_newfile($cmds)
957 {
958 $targetFolderObject = $this->getFileObject($cmds['target']);
959 if (!$targetFolderObject instanceof Folder) {
960 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::SYSTEM_ERROR, 104, 'Destination "%s" was not a directory', [$cmds['target']]);
961 $this->addMessageToFlashMessageQueue('FileUtility.DestinationWasNotADirectory', [$cmds['target']]);
962 return false;
963 }
964 $resultObject = null;
965 $fileName = $cmds['data'];
966 try {
967 $resultObject = $targetFolderObject->createFile($fileName);
968 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::MESSAGE, 1, 'File created: "%s"', [$fileName]);
969 if ($resultObject->getName() !== $fileName) {
970 $this->addMessageToFlashMessageQueue('FileUtility.FileNameSanitized', [$fileName, $resultObject->getName()], FlashMessage::WARNING);
971 }
972 $this->addMessageToFlashMessageQueue('FileUtility.FileCreated', [$resultObject->getName()], FlashMessage::OK);
973 } catch (IllegalFileExtensionException $e) {
974 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::USER_ERROR, 106, 'Extension of file "%s" was not allowed!', [$fileName]);
975 $this->addMessageToFlashMessageQueue('FileUtility.ExtensionOfFileWasNotAllowed', [$fileName]);
976 } catch (InsufficientFolderWritePermissionsException $e) {
977 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::USER_ERROR, 103, 'You are not allowed to create files!', []);
978 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToCreateFiles');
979 } catch (NotInMountPointException $e) {
980 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::USER_ERROR, 102, 'Destination path "%s" was not within your mountpoints!', [$targetFolderObject->getIdentifier()]);
981 $this->addMessageToFlashMessageQueue('FileUtility.DestinationPathWasNotWithinYourMountpoints', [$targetFolderObject->getIdentifier()]);
982 } catch (ExistingTargetFileNameException $e) {
983 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::USER_ERROR, 101, 'File existed already in "%s"!', [$targetFolderObject->getIdentifier()]);
984 $this->addMessageToFlashMessageQueue('FileUtility.FileExistedAlreadyIn', [$targetFolderObject->getIdentifier()]);
985 } catch (InvalidFileNameException $e) {
986 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::USER_ERROR, 106, 'File name "%s" was not allowed!', [$fileName]);
987 $this->addMessageToFlashMessageQueue('FileUtility.FileNameWasNotAllowed', [$fileName]);
988 } catch (\RuntimeException $e) {
989 $this->writeLog(SystemLogFileAction::NEW_FILE, SystemLogErrorClassification::USER_ERROR, 100, 'File "%s" was not created! Write-permission problem in "%s"?', [$fileName, $targetFolderObject->getIdentifier()]);
990 $this->addMessageToFlashMessageQueue('FileUtility.FileWasNotCreated', [$fileName, $targetFolderObject->getIdentifier()]);
991 }
992 return $resultObject;
993 }
994
995 /**
996 * Editing textfiles or folders (action=9)
997 *
998 * @param array $cmds $cmds['data'] is the new content. $cmds['target'] is the target (file or dir)
999 * @return bool Returns TRUE on success
1000 */
1001 public function func_edit($cmds)
1002 {
1003 // Example identifier for $cmds['target'] => "4:mypath/tomyfolder/myfile.jpg"
1004 // for backwards compatibility: the combined file identifier was the path+filename
1005 $fileIdentifier = $cmds['target'];
1006 $fileObject = $this->getFileObject($fileIdentifier);
1007 if (!$fileObject instanceof File) {
1008 $this->writeLog(SystemLogFileAction::EDIT, SystemLogErrorClassification::SYSTEM_ERROR, 123, 'Target "%s" was not a file!', [$fileIdentifier]);
1009 $this->addMessageToFlashMessageQueue('FileUtility.TargetWasNotAFile', [$fileIdentifier]);
1010 return false;
1011 }
1012 if (!$fileObject->isTextFile()) {
1013 $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'];
1014 $this->writeLog(SystemLogFileAction::EDIT, SystemLogErrorClassification::USER_ERROR, 102, 'File extension "%s" is not a textfile format! (%s)', [$fileObject->getExtension(), $extList]);
1015 $this->addMessageToFlashMessageQueue('FileUtility.FileExtensionIsNotATextfileFormat', [$fileObject->getExtension(), $extList]);
1016 return false;
1017 }
1018 try {
1019 // Example identifier for $cmds['target'] => "2:targetpath/targetfolder/"
1020 $content = $cmds['data'];
1021 $fileObject->setContents($content);
1022 clearstatcache();
1023 $this->writeLog(SystemLogFileAction::EDIT, SystemLogErrorClassification::MESSAGE, 1, 'File saved to "%s", bytes: %s, MD5: %s ', [$fileObject->getIdentifier(), $fileObject->getSize(), md5($content)]);
1024 $this->addMessageToFlashMessageQueue('FileUtility.FileSavedToBytesMd5', [$fileObject->getIdentifier(), $fileObject->getSize(), md5($content)], FlashMessage::OK);
1025 return true;
1026 } catch (InsufficientUserPermissionsException $e) {
1027 $this->writeLog(SystemLogFileAction::EDIT, SystemLogErrorClassification::USER_ERROR, 104, 'You are not allowed to edit files!', []);
1028 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToEditFiles');
1029 return false;
1030 } catch (InsufficientFileWritePermissionsException $e) {
1031 $this->writeLog(SystemLogFileAction::EDIT, SystemLogErrorClassification::USER_ERROR, 100, 'File "%s" was not saved! Write-permission problem?', [$fileObject->getIdentifier()]);
1032 $this->addMessageToFlashMessageQueue('FileUtility.FileWasNotSaved', [$fileObject->getIdentifier()]);
1033 return false;
1034 } catch (IllegalFileExtensionException|\RuntimeException $e) {
1035 $this->writeLog(SystemLogFileAction::EDIT, SystemLogErrorClassification::USER_ERROR, 100, 'File "%s" was not saved! File extension rejected!', [$fileObject->getIdentifier()]);
1036 $this->addMessageToFlashMessageQueue('FileUtility.FileWasNotSaved', [$fileObject->getIdentifier()]);
1037 return false;
1038 }
1039 }
1040
1041 /**
1042 * Upload of files (action=1)
1043 * when having multiple uploads (HTML5-style), the array $_FILES looks like this:
1044 * Array(
1045 * [upload_1] => Array(
1046 * [name] => Array(
1047 * [0] => GData - Content-Elements and Media-Gallery.pdf
1048 * [1] => CMS Expo 2011.txt
1049 * )
1050 * [type] => Array(
1051 * [0] => application/pdf
1052 * [1] => text/plain
1053 * )
1054 * [tmp_name] => Array(
1055 * [0] => /Applications/MAMP/tmp/php/phpNrOB43
1056 * [1] => /Applications/MAMP/tmp/php/phpD2HQAK
1057 * )
1058 * [size] => Array(
1059 * [0] => 373079
1060 * [1] => 1291
1061 * )
1062 * )
1063 * )
1064 * in HTML you'd need sth like this: <input type="file" name="upload_1[]" multiple="true" />
1065 *
1066 * @param array $cmds $cmds['data'] is the ID-number (points to the global var that holds the filename-ref
1067 * ($_FILES['upload_' . $id]['name']) . $cmds['target'] is the target directory, $cmds['charset']
1068 * is the the character set of the file name (utf-8 is needed for JS-interaction)
1069 * @return File[]|bool Returns an array of new file objects upon success. False otherwise
1070 */
1071 public function func_upload($cmds)
1072 {
1073 $uploadPosition = $cmds['data'];
1074 $uploadedFileData = $_FILES['upload_' . $uploadPosition];
1075 if (empty($uploadedFileData['name']) || is_array($uploadedFileData['name']) && empty($uploadedFileData['name'][0])) {
1076 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::SYSTEM_ERROR, 108, 'No file was uploaded!', []);
1077 $this->addMessageToFlashMessageQueue('FileUtility.NoFileWasUploaded');
1078 return false;
1079 }
1080 // Example identifier for $cmds['target'] => "2:targetpath/targetfolder/"
1081 $targetFolderObject = $this->getFileObject($cmds['target']);
1082 // Uploading with non HTML-5-style, thus, make an array out of it, so we can loop over it
1083 if (!is_array($uploadedFileData['name'])) {
1084 $uploadedFileData = [
1085 'name' => [$uploadedFileData['name']],
1086 'type' => [$uploadedFileData['type']],
1087 'tmp_name' => [$uploadedFileData['tmp_name']],
1088 'size' => [$uploadedFileData['size']],
1089 ];
1090 }
1091 $resultObjects = [];
1092 $numberOfUploadedFilesForPosition = count($uploadedFileData['name']);
1093 // Loop through all uploaded files
1094 for ($i = 0; $i < $numberOfUploadedFilesForPosition; $i++) {
1095 $fileInfo = [
1096 'name' => $uploadedFileData['name'][$i],
1097 'type' => $uploadedFileData['type'][$i],
1098 'tmp_name' => $uploadedFileData['tmp_name'][$i],
1099 'size' => $uploadedFileData['size'][$i],
1100 ];
1101 try {
1102 $fileObject = $targetFolderObject->addUploadedFile($fileInfo, (string)$this->existingFilesConflictMode);
1103 if ($this->existingFilesConflictMode->equals(DuplicationBehavior::REPLACE)) {
1104 $this->getIndexer($fileObject->getStorage())->updateIndexEntry($fileObject);
1105 }
1106 $resultObjects[] = $fileObject;
1107 $this->internalUploadMap[$uploadPosition] = $fileObject->getCombinedIdentifier();
1108 if ($fileObject->getName() !== $fileInfo['name']) {
1109 $this->addMessageToFlashMessageQueue('FileUtility.FileNameSanitized', [$fileInfo['name'], $fileObject->getName()], FlashMessage::WARNING);
1110 }
1111 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::MESSAGE, 1, 'Uploading file "%s" to "%s"', [$fileInfo['name'], $targetFolderObject->getIdentifier()]);
1112 $this->addMessageToFlashMessageQueue('FileUtility.UploadingFileTo', [$fileInfo['name'], $targetFolderObject->getIdentifier()], FlashMessage::OK);
1113 } catch (InsufficientFileWritePermissionsException $e) {
1114 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 107, 'You are not allowed to override "%s"!', [$fileInfo['name']]);
1115 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToOverride', [$fileInfo['name']]);
1116 } catch (UploadException $e) {
1117 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::SYSTEM_ERROR, 106, 'The upload has failed, no uploaded file found!', []);
1118 $this->addMessageToFlashMessageQueue('FileUtility.TheUploadHasFailedNoUploadedFileFound');
1119 } catch (InsufficientUserPermissionsException $e) {
1120 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 105, 'You are not allowed to upload files!', []);
1121 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToUploadFiles');
1122 } catch (UploadSizeException $e) {
1123 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 104, 'The uploaded file "%s" exceeds the size-limit', [$fileInfo['name']]);
1124 $this->addMessageToFlashMessageQueue('FileUtility.TheUploadedFileExceedsTheSize-limit', [$fileInfo['name']]);
1125 } catch (InsufficientFolderWritePermissionsException $e) {
1126 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 103, 'Destination path "%s" was not within your mountpoints!', [$targetFolderObject->getIdentifier()]);
1127 $this->addMessageToFlashMessageQueue('FileUtility.DestinationPathWasNotWithinYourMountpoints', [$targetFolderObject->getIdentifier()]);
1128 } catch (IllegalFileExtensionException $e) {
1129 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 102, 'Extension of file name "%s" is not allowed in "%s"!', [$fileInfo['name'], $targetFolderObject->getIdentifier()]);
1130 $this->addMessageToFlashMessageQueue('FileUtility.ExtensionOfFileNameIsNotAllowedIn', [$fileInfo['name'], $targetFolderObject->getIdentifier()]);
1131 } catch (ExistingTargetFileNameException $e) {
1132 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 101, 'No unique filename available in "%s"!', [$targetFolderObject->getIdentifier()]);
1133 $this->addMessageToFlashMessageQueue('FileUtility.NoUniqueFilenameAvailableIn', [$targetFolderObject->getIdentifier()]);
1134 } catch (\RuntimeException $e) {
1135 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 100, 'Uploaded file could not be moved! Write-permission problem in "%s"?', [$targetFolderObject->getIdentifier()]);
1136 $this->addMessageToFlashMessageQueue('FileUtility.UploadedFileCouldNotBeMoved', [$targetFolderObject->getIdentifier()]);
1137 }
1138 }
1139
1140 return $resultObjects;
1141 }
1142
1143 /**
1144 * Replaces a file on the filesystem and changes the identifier of the persisted file object in sys_file if
1145 * keepFilename is not checked. If keepFilename is checked, only the file content will be replaced.
1146 *
1147 * @param array $cmdArr
1148 * @return array|bool
1149 * @throws Exception\InsufficientFileAccessPermissionsException
1150 * @throws Exception\InvalidFileException
1151 * @throws \RuntimeException
1152 */
1153 protected function replaceFile(array $cmdArr)
1154 {
1155 $fileObjectToReplace = null;
1156 $uploadPosition = $cmdArr['data'];
1157 $fileInfo = $_FILES['replace_' . $uploadPosition];
1158 if (empty($fileInfo['name'])) {
1159 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::SYSTEM_ERROR, 108, 'No file was uploaded for replacing!', []);
1160 $this->addMessageToFlashMessageQueue('FileUtility.NoFileWasUploadedForReplacing');
1161 return false;
1162 }
1163
1164 $keepFileName = (bool)($cmdArr['keepFilename'] ?? false);
1165 $resultObjects = [];
1166
1167 try {
1168 $fileObjectToReplace = $this->getFileObject($cmdArr['uid']);
1169 $folder = $fileObjectToReplace->getParentFolder();
1170 $resourceStorage = $fileObjectToReplace->getStorage();
1171
1172 $fileObject = $resourceStorage->addUploadedFile($fileInfo, $folder, $fileObjectToReplace->getName(), DuplicationBehavior::REPLACE);
1173
1174 // Check if there is a file that is going to be uploaded that has a different name as the replacing one
1175 // but exists in that folder as well.
1176 // rename to another name, but check if the name is already given
1177 if ($keepFileName === false) {
1178 // if a file with the same name already exists, we need to change it to _01 etc.
1179 // if the file does not exist, we can do a simple rename
1180 $resourceStorage->moveFile($fileObject, $folder, $fileInfo['name'], DuplicationBehavior::RENAME);
1181 }
1182
1183 $resultObjects[] = $fileObject;
1184 $this->internalUploadMap[$uploadPosition] = $fileObject->getCombinedIdentifier();
1185
1186 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::MESSAGE, 1, 'Replacing file "%s" to "%s"', [$fileInfo['name'], $fileObjectToReplace->getIdentifier()]);
1187 $this->addMessageToFlashMessageQueue('FileUtility.ReplacingFileTo', [$fileInfo['name'], $fileObjectToReplace->getIdentifier()], FlashMessage::OK);
1188 } catch (InsufficientFileWritePermissionsException $e) {
1189 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 107, 'You are not allowed to override "%s"!', [$fileInfo['name']]);
1190 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToOverride', [$fileInfo['name']]);
1191 } catch (UploadException $e) {
1192 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::SYSTEM_ERROR, 106, 'The upload has failed, no uploaded file found!', []);
1193 $this->addMessageToFlashMessageQueue('FileUtility.TheUploadHasFailedNoUploadedFileFound');
1194 } catch (InsufficientUserPermissionsException $e) {
1195 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 105, 'You are not allowed to upload files!', []);
1196 $this->addMessageToFlashMessageQueue('FileUtility.YouAreNotAllowedToUploadFiles');
1197 } catch (UploadSizeException $e) {
1198 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 104, 'The uploaded file "%s" exceeds the size-limit', [$fileInfo['name']]);
1199 $this->addMessageToFlashMessageQueue('FileUtility.TheUploadedFileExceedsTheSize-limit', [$fileInfo['name']]);
1200 } catch (InsufficientFolderWritePermissionsException $e) {
1201 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 103, 'Destination path "%s" was not within your mountpoints!', [$fileObjectToReplace->getIdentifier()]);
1202 $this->addMessageToFlashMessageQueue('FileUtility.DestinationPathWasNotWithinYourMountpoints', [$fileObjectToReplace->getIdentifier()]);
1203 } catch (IllegalFileExtensionException $e) {
1204 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 102, 'Extension of file name "%s" is not allowed in "%s"!', [$fileInfo['name'], $fileObjectToReplace->getIdentifier()]);
1205 $this->addMessageToFlashMessageQueue('FileUtility.ExtensionOfFileNameIsNotAllowedIn', [$fileInfo['name'], $fileObjectToReplace->getIdentifier()]);
1206 } catch (ExistingTargetFileNameException $e) {
1207 $this->writeLog(SystemLogFileAction::UPLOAD, SystemLogErrorClassification::USER_ERROR, 101, 'No unique filename available in "%s"!', [$fileObjectToReplace->getIdentifier()]);
1208 $this->addMessageToFlashMessageQueue('FileUtility.NoUniqueFilenameAvailableIn', [$fileObjectToReplace->getIdentifier()]);
1209 } catch (\RuntimeException $e) {
1210 throw $e;
1211 }
1212 return $resultObjects;
1213 }
1214
1215 /**
1216 * Add flash message to message queue
1217 *
1218 * @param FlashMessage $flashMessage
1219 */
1220 protected function addFlashMessage(FlashMessage $flashMessage)
1221 {
1222 /** @var FlashMessageService $flashMessageService */
1223 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1224
1225 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */
1226 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1227 $defaultFlashMessageQueue->enqueue($flashMessage);
1228 }
1229
1230 /**
1231 * Gets Indexer
1232 *
1233 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storage
1234 * @return \TYPO3\CMS\Core\Resource\Index\Indexer
1235 */
1236 protected function getIndexer(ResourceStorage $storage)
1237 {
1238 return GeneralUtility::makeInstance(Indexer::class, $storage);
1239 }
1240
1241 /**
1242 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
1243 */
1244 protected function getBackendUser()
1245 {
1246 return $GLOBALS['BE_USER'];
1247 }
1248
1249 /**
1250 * Returns LanguageService
1251 *
1252 * @return LanguageService
1253 */
1254 protected function getLanguageService()
1255 {
1256 return $GLOBALS['LANG'];
1257 }
1258 }