TYPO3 CMS  TYPO3_6-2
ResourceStorage.php
Go to the documentation of this file.
1 <?php
3 
21 
58 
64  protected $driver;
65 
71  protected $storageRecord;
72 
78  protected $configuration;
79 
84 
93  protected $evaluatePermissions = FALSE;
94 
100  protected $fileMounts = array();
101 
108  protected $userPermissions = array();
109 
116  protected $capabilities;
117 
122 
126  protected $processingFolder;
127 
134 
140  protected $isOnline = NULL;
141 
145  protected $isDefault = FALSE;
146 
152  protected $fileAndFolderNameFilters = array();
153 
160  public function __construct(Driver\DriverInterface $driver, array $storageRecord) {
161  $this->storageRecord = $storageRecord;
162  $this->configuration = ResourceFactory::getInstance()->convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
163  $this->capabilities =
164  ($this->storageRecord['is_browsable'] ? self::CAPABILITY_BROWSABLE : 0) |
165  ($this->storageRecord['is_public'] ? self::CAPABILITY_PUBLIC : 0) |
166  ($this->storageRecord['is_writable'] ? self::CAPABILITY_WRITABLE : 0);
167 
168  $this->driver = $driver;
169  $this->driver->setStorageUid($storageRecord['uid']);
170  $this->driver->mergeConfigurationCapabilities($this->capabilities);
171  try {
172  $this->driver->processConfiguration();
173  } catch (Exception\InvalidConfigurationException $e) {
174  // configuration error
175  // mark this storage as permanently unusable
176  $this->markAsPermanentlyOffline();
177  }
178  $this->driver->initialize();
179  $this->capabilities = $this->driver->getCapabilities();
180 
181  $this->isDefault = (isset($storageRecord['is_default']) && $storageRecord['is_default'] == 1);
183  }
184 
190  public function getConfiguration() {
191  return $this->configuration;
192  }
193 
199  public function setConfiguration(array $configuration) {
200  $this->configuration = $configuration;
201  }
202 
208  public function getStorageRecord() {
209  return $this->storageRecord;
210  }
211 
218  public function setDriver(Driver\DriverInterface $driver) {
219  $this->driver = $driver;
220  return $this;
221  }
222 
228  protected function getDriver() {
229  return $this->driver;
230  }
231 
239  public function getFolderByIdentifier($identifier) {
240  throw new \BadMethodCallException(
241  'Function TYPO3\\CMS\\Core\\Resource\\ResourceStorage::getFolderByIdentifier() has been renamed to just getFolder(). Please fix the method call.',
242  1333754514
243  );
244  }
245 
253  public function getFileByIdentifier($identifier) {
254  throw new \BadMethodCallException(
255  'Function TYPO3\\CMS\\Core\\Resource\\ResourceStorage::getFileByIdentifier() has been renamed to just getFileInfoByIdentifier(). ' . 'Please fix the method call.',
256  1333754533
257  );
258  }
259 
265  public function getName() {
266  return $this->storageRecord['name'];
267  }
268 
274  public function getUid() {
275  return (int)$this->storageRecord['uid'];
276  }
277 
283  public function hasChildren() {
284  return TRUE;
285  }
286 
287  /*********************************
288  * Capabilities
289  ********************************/
296  public function getCapabilities() {
297  return (int)$this->capabilities;
298  }
299 
306  protected function hasCapability($capability) {
307  return ($this->capabilities & $capability) == $capability;
308  }
309 
318  public function isPublic() {
319  return $this->hasCapability(self::CAPABILITY_PUBLIC);
320  }
321 
328  public function isWritable() {
329  return $this->hasCapability(self::CAPABILITY_WRITABLE);
330  }
331 
337  public function isBrowsable() {
338  return $this->isOnline() && $this->hasCapability(self::CAPABILITY_BROWSABLE);
339  }
340 
346  public function usesCaseSensitiveIdentifiers() {
347  return $this->driver->isCaseSensitiveFileSystem();
348  }
349 
355  public function isOnline() {
356  if ($this->isOnline === NULL) {
357  if ($this->getUid() === 0) {
358  $this->isOnline = TRUE;
359  }
360  // the storage is not marked as online for a longer time
361  if ($this->storageRecord['is_online'] == 0) {
362  $this->isOnline = FALSE;
363  }
364  if ($this->isOnline !== FALSE) {
365  // all files are ALWAYS available in the frontend
366  if (TYPO3_MODE === 'FE') {
367  $this->isOnline = TRUE;
368  } else {
369  // check if the storage is disabled temporary for now
370  $registryObject = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Registry');
371  $offlineUntil = $registryObject->get('core', 'sys_file_storage-' . $this->getUid() . '-offline-until');
372  if ($offlineUntil && $offlineUntil > time()) {
373  $this->isOnline = FALSE;
374  } else {
375  $this->isOnline = TRUE;
376  }
377  }
378  }
379  }
380  return $this->isOnline;
381  }
382 
392  public function markAsPermanentlyOffline() {
393  if ($this->getUid() > 0) {
394  // @todo: move this to the storage repository
395  $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_file_storage', 'uid=' . (int)$this->getUid(), array('is_online' => 0));
396  }
397  $this->storageRecord['is_online'] = 0;
398  $this->isOnline = FALSE;
399  }
400 
409  public function markAsTemporaryOffline() {
410  $registryObject = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Registry');
411  $registryObject->set('core', 'sys_file_storage-' . $this->getUid() . '-offline-until', time() + 60 * 5);
412  $this->storageRecord['is_online'] = 0;
413  $this->isOnline = FALSE;
414  }
415 
416  /*********************************
417  * User Permissions / File Mounts
418  ********************************/
429  public function addFileMount($folderIdentifier, $additionalData = array()) {
430  // check for the folder before we add it as a filemount
431  if ($this->driver->folderExists($folderIdentifier) === FALSE) {
432  // if there is an error, this is important and should be handled
433  // as otherwise the user would see the whole storage without any restrictions for the filemounts
434  throw new Exception\FolderDoesNotExistException('Folder for file mount ' . $folderIdentifier . ' does not exist.', 1334427099);
435  }
436  $data = $this->driver->getFolderInfoByIdentifier($folderIdentifier);
437  $folderObject = ResourceFactory::getInstance()->createFolderObject($this, $data['identifier'], $data['name']);
438  // Use the canonical identifier instead of the user provided one!
439  $folderIdentifier = $folderObject->getIdentifier();
440  if (
441  !empty($this->fileMounts[$folderIdentifier])
442  && empty($this->fileMounts[$folderIdentifier]['read_only'])
443  && !empty($additionalData['read_only'])
444  ) {
445  // Do not overwrite a regular mount with a read only mount
446  return;
447  }
448  if (empty($additionalData)) {
449  $additionalData = array(
450  'path' => $folderIdentifier,
451  'title' => $folderIdentifier,
452  'folder' => $folderObject
453  );
454  } else {
455  $additionalData['folder'] = $folderObject;
456  if (!isset($additionalData['title'])) {
457  $additionalData['title'] = $folderIdentifier;
458  }
459  }
460  $this->fileMounts[$folderIdentifier] = $additionalData;
461  }
462 
468  public function getFileMounts() {
469  return $this->fileMounts;
470  }
471 
480  public function isWithinFileMountBoundaries($subject, $checkWriteAccess = FALSE) {
481  if (!$this->evaluatePermissions) {
482  return TRUE;
483  }
484  $isWithinFileMount = FALSE;
485  if (!$subject) {
486  $subject = $this->getRootLevelFolder();
487  }
488  $identifier = $subject->getIdentifier();
489 
490  // Allow access to processing folder
491  if ($this->isWithinProcessingFolder($identifier)) {
492  $isWithinFileMount = TRUE;
493  } else {
494  // Check if the identifier of the subject is within at
495  // least one of the file mounts
496  $writableFileMountAvailable = FALSE;
497  foreach ($this->fileMounts as $fileMount) {
498  if ($this->driver->isWithin($fileMount['folder']->getIdentifier(), $identifier)) {
499  $isWithinFileMount = TRUE;
500  if (!$checkWriteAccess) {
501  break;
502  } elseif (empty($fileMount['read_only'])) {
503  $writableFileMountAvailable = TRUE;
504  break;
505  }
506  }
507  }
508  $isWithinFileMount = $checkWriteAccess ? $writableFileMountAvailable : $isWithinFileMount;
509  }
510  return $isWithinFileMount;
511  }
512 
520  $this->evaluatePermissions = (bool)$evaluatePermissions;
521  }
522 
529  public function getEvaluatePermissions() {
531  }
532 
539  public function setUserPermissions(array $userPermissions) {
540  $this->userPermissions = $userPermissions;
541  }
542 
551  public function checkUserActionPermission($action, $type) {
552  if (!$this->evaluatePermissions) {
553  return TRUE;
554  }
555 
556  $allow = FALSE;
557  if (!empty($this->userPermissions[strtolower($action) . ucfirst(strtolower($type))])) {
558  $allow = TRUE;
559  }
560 
561  return $allow;
562  }
563 
577  public function checkFileActionPermission($action, FileInterface $file) {
578  $isProcessedFile = $file instanceof ProcessedFile;
579  // Check 1: Does the user have permission to perform the action? e.g. "readFile"
580  if (!$isProcessedFile && $this->checkUserActionPermission($action, 'File') === FALSE) {
581  return FALSE;
582  }
583  // Check 2: No action allowed on files for denied file extensions
584  if (!$this->checkFileExtensionPermission($file->getName())) {
585  return FALSE;
586  }
587  $isReadCheck = FALSE;
588  if (in_array($action, array('read', 'copy', 'move'), TRUE)) {
589  $isReadCheck = TRUE;
590  }
591  $isWriteCheck = FALSE;
592  if (in_array($action, array('add', 'write', 'move', 'rename', 'unzip', 'delete'), TRUE)) {
593  $isWriteCheck = TRUE;
594  }
595  // Check 3: Does the user have the right to perform the action?
596  // (= is he within the file mount borders)
597  if (!$isProcessedFile && !$this->isWithinFileMountBoundaries($file, $isWriteCheck)) {
598  return FALSE;
599  }
600 
601  $isMissing = FALSE;
602  if (!$isProcessedFile && $file instanceof File) {
603  $isMissing = $file->isMissing();
604  }
605 
606  if ($this->driver->fileExists($file->getIdentifier()) === FALSE) {
607  $file->setMissing(TRUE);
608  $isMissing = TRUE;
609  }
610 
611  // Check 4: Check the capabilities of the storage (and the driver)
612  if ($isWriteCheck && ($isMissing || !$this->isWritable())) {
613  return FALSE;
614  }
615 
616  // Check 5: "File permissions" of the driver (only when file isn't marked as missing)
617  if (!$isMissing) {
618  $filePermissions = $this->driver->getPermissions($file->getIdentifier());
619  if ($isReadCheck && !$filePermissions['r']) {
620  return FALSE;
621  }
622  if ($isWriteCheck && !$filePermissions['w']) {
623  return FALSE;
624  }
625  }
626  return TRUE;
627  }
628 
639  public function checkFolderActionPermission($action, Folder $folder = NULL) {
640  // Check 1: Does the user have permission to perform the action? e.g. "writeFolder"
641  if ($this->checkUserActionPermission($action, 'Folder') === FALSE) {
642  return FALSE;
643  }
644 
645  // If we do not have a folder here, we cannot do further checks
646  if ($folder === NULL) {
647  return TRUE;
648  }
649 
650  $isReadCheck = FALSE;
651  if (in_array($action, array('read', 'copy'), TRUE)) {
652  $isReadCheck = TRUE;
653  }
654  $isWriteCheck = FALSE;
655  if (in_array($action, array('add', 'move', 'write', 'delete', 'rename'), TRUE)) {
656  $isWriteCheck = TRUE;
657  }
658  // Check 2: Does the user has the right to perform the action?
659  // (= is he within the file mount borders)
660  if (!$this->isWithinFileMountBoundaries($folder, $isWriteCheck)) {
661  return FALSE;
662  }
663  // Check 3: Check the capabilities of the storage (and the driver)
664  if ($isReadCheck && !$this->isBrowsable()) {
665  return FALSE;
666  }
667  if ($isWriteCheck && !$this->isWritable()) {
668  return FALSE;
669  }
670 
671  // Check 4: "Folder permissions" of the driver
672  $folderPermissions = $this->driver->getPermissions($folder->getIdentifier());
673  if ($isReadCheck && !$folderPermissions['r']) {
674  return FALSE;
675  }
676  if ($isWriteCheck && !$folderPermissions['w']) {
677  return FALSE;
678  }
679  return TRUE;
680  }
681 
689  protected function checkFileExtensionPermission($fileName) {
690  $fileName = $this->driver->sanitizeFileName($fileName);
691  $isAllowed = GeneralUtility::verifyFilenameAgainstDenyPattern($fileName);
692  if ($isAllowed && $this->evaluatePermissions) {
693  $fileExtension = strtolower(PathUtility::pathinfo($fileName, PATHINFO_EXTENSION));
694  // Set up the permissions for the file extension
695  $fileExtensionPermissions = $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']['webspace'];
696  $fileExtensionPermissions['allow'] = GeneralUtility::uniqueList(strtolower($fileExtensionPermissions['allow']));
697  $fileExtensionPermissions['deny'] = GeneralUtility::uniqueList(strtolower($fileExtensionPermissions['deny']));
698  if ($fileExtension !== '') {
699  // If the extension is found amongst the allowed types, we return TRUE immediately
700  if ($fileExtensionPermissions['allow'] === '*' || GeneralUtility::inList($fileExtensionPermissions['allow'], $fileExtension)) {
701  return TRUE;
702  }
703  // If the extension is found amongst the denied types, we return FALSE immediately
704  if ($fileExtensionPermissions['deny'] === '*' || GeneralUtility::inList($fileExtensionPermissions['deny'], $fileExtension)) {
705  return FALSE;
706  }
707  // If no match we return TRUE
708  return TRUE;
709  } else {
710  if ($fileExtensionPermissions['allow'] === '*') {
711  return TRUE;
712  }
713  if ($fileExtensionPermissions['deny'] === '*') {
714  return FALSE;
715  }
716  return TRUE;
717  }
718  }
719  return $isAllowed;
720  }
721 
729  protected function assureFolderReadPermission(Folder $folder = NULL) {
730  if (!$this->checkFolderActionPermission('read', $folder)) {
731  if ($folder === NULL) {
732  throw new Exception\InsufficientFolderAccessPermissionsException(
733  'You are not allowed to read folders',
734  1430657869
735  );
736  } else {
737  throw new Exception\InsufficientFolderAccessPermissionsException(
738  'You are not allowed to access the given folder: "' . $folder->getName() . '"',
739  1375955684
740  );
741  }
742  }
743  }
744 
755  protected function assureFolderDeletePermission(Folder $folder, $checkDeleteRecursively) {
756  // Check user permissions for recursive deletion if it is requested
757  if ($checkDeleteRecursively && !$this->checkUserActionPermission('recursivedelete', 'Folder')) {
758  throw new Exception\InsufficientUserPermissionsException('You are not allowed to delete folders recursively', 1377779423);
759  }
760  // Check user action permission
761  if (!$this->checkFolderActionPermission('delete', $folder)) {
762  throw new Exception\InsufficientFolderAccessPermissionsException('You are not allowed to delete the given folder', 1377779039);
763  }
764  // Check if the user has write permissions to folders
765  // Would be good if we could check for actual write permissions in the containig folder
766  // but we cannot since we have no access to the containing folder of this file.
767  if (!$this->checkUserActionPermission('write', 'Folder')) {
768  throw new Exception\InsufficientFolderWritePermissionsException('Writing to folders is not allowed.', 1377779111);
769  }
770  }
771 
780  protected function assureFileReadPermission(FileInterface $file) {
781  if (!$this->checkFileActionPermission('read', $file)) {
782  throw new Exception\InsufficientFileAccessPermissionsException('You are not allowed to access that file.', 1375955429);
783  }
784  if (!$this->checkFileExtensionPermission($file->getName())) {
785  throw new Exception\IllegalFileExtensionException('You are not allowed to use that file extension', 1375955430);
786  }
787  }
788 
798  protected function assureFileWritePermissions(FileInterface $file) {
799  // Check if user is allowed to write the file and $file is writable
800  if (!$this->checkFileActionPermission('write', $file)) {
801  throw new Exception\InsufficientFileWritePermissionsException('Writing to file "' . $file->getIdentifier() . '" is not allowed.', 1330121088);
802  }
803  if (!$this->checkFileExtensionPermission($file->getName())) {
804  throw new Exception\IllegalFileExtensionException('You are not allowed to edit a file with extension "' . $file->getExtension() . '"', 1366711933);
805  }
806  }
807 
817  protected function assureFileDeletePermissions(FileInterface $file) {
818  // Check for disallowed file extensions
819  if (!$this->checkFileExtensionPermission($file->getName())) {
820  throw new Exception\IllegalFileExtensionException('You are not allowed to delete a file with extension "' . $file->getExtension() . '"', 1377778916);
821  }
822  // Check further permissions if file is not a processed file
823  if (!$file instanceof ProcessedFile) {
824  // Check if user is allowed to delete the file and $file is writable
825  if (!$this->checkFileActionPermission('delete', $file)) {
826  throw new Exception\InsufficientFileWritePermissionsException('You are not allowed to delete the file "' . $file->getIdentifier() . '"', 1319550425);
827  }
828  // Check if the user has write permissions to folders
829  // Would be good if we could check for actual write permissions in the containig folder
830  // but we cannot since we have no access to the containing folder of this file.
831  if (!$this->checkUserActionPermission('write', 'Folder')) {
832  throw new Exception\InsufficientFolderWritePermissionsException('Writing to folders is not allowed.', 1377778702);
833  }
834  }
835  }
836 
852  protected function assureFileAddPermissions($localFilePath, $targetFolder, $targetFileName) {
853  // Check for a valid file extension
854  if (!$this->checkFileExtensionPermission($targetFileName)) {
855  throw new Exception\IllegalFileExtensionException('Extension of file name is not allowed in "' . $targetFileName . '"!', 1322120271);
856  }
857  // Makes sure the user is allowed to upload
858  if (!$this->checkUserActionPermission('add', 'File')) {
859  throw new Exception\InsufficientUserPermissionsException('You are not allowed to add files to this storage "' . $this->getUid() . '"', 1376992145);
860  }
861  // Check if targetFolder is writable
862  if (!$this->checkFolderActionPermission('write', $targetFolder)) {
863  throw new Exception\InsufficientFolderWritePermissionsException('You are not allowed to write to the target folder "' . $targetFolder->getIdentifier() . '"', 1322120356);
864  }
865  }
866 
883  protected function assureFileUploadPermissions($localFilePath, $targetFolder, $targetFileName, $uploadedFileSize) {
884  // Makes sure this is an uploaded file
885  if (!is_uploaded_file($localFilePath)) {
886  throw new Exception\UploadException('The upload has failed, no uploaded file found!', 1322110455);
887  }
888  // Max upload size (kb) for files.
889  $maxUploadFileSize = GeneralUtility::getMaxUploadFileSize() * 1024;
890  if ($uploadedFileSize >= $maxUploadFileSize) {
891  unlink($localFilePath);
892  throw new Exception\UploadSizeException('The uploaded file exceeds the size-limit of ' . $maxUploadFileSize . ' bytes', 1322110041);
893  }
894  $this->assureFileAddPermissions('', $targetFolder, $targetFileName);
895  }
896 
909  protected function assureFileMovePermissions(FileInterface $file, Folder $targetFolder, $targetFileName) {
910  // Check if targetFolder is within this storage
911  if ($this->getUid() !== $targetFolder->getStorage()->getUid()) {
912  throw new \RuntimeException();
913  }
914  // Check for a valid file extension
915  if (!$this->checkFileExtensionPermission($targetFileName)) {
916  throw new Exception\IllegalFileExtensionException('Extension of file name is not allowed in "' . $targetFileName . '"!', 1378243279);
917  }
918  // Check if user is allowed to move and $file is readable and writable
919  if (!$file->getStorage()->checkFileActionPermission('move', $file)) {
920  throw new Exception\InsufficientUserPermissionsException('You are not allowed to move files to storage "' . $this->getUid() . '"', 1319219349);
921  }
922  // Check if target folder is writable
923  if (!$this->checkFolderActionPermission('write', $targetFolder)) {
924  throw new Exception\InsufficientFolderAccessPermissionsException('You are not allowed to write to the target folder "' . $targetFolder->getIdentifier() . '"', 1319219350);
925  }
926  }
927 
939  protected function assureFileRenamePermissions(FileInterface $file, $targetFileName) {
940  // Check if file extension is allowed
941  if (!$this->checkFileExtensionPermission($targetFileName) || !$this->checkFileExtensionPermission($file->getName())) {
942  throw new Exception\IllegalFileExtensionException('You are not allowed to rename a file with to this extension', 1371466663);
943  }
944  // Check if user is allowed to rename
945  if (!$this->checkFileActionPermission('rename', $file)) {
946  throw new Exception\InsufficientUserPermissionsException('You are not allowed to rename files."', 1319219351);
947  }
948  // Check if the user is allowed to write to folders
949  // Although it would be good to check, we cannot check here if the folder actually is writable
950  // because we do not know in which folder the file resides.
951  // So we rely on the driver to throw an exception in case the renaming failed.
952  if (!$this->checkFolderActionPermission('write')) {
953  throw new Exception\InsufficientFileWritePermissionsException('You are not allowed to write to folders', 1319219352);
954  }
955  }
956 
972  protected function assureFileCopyPermissions(FileInterface $file, Folder $targetFolder, $targetFileName) {
973  // Check if targetFolder is within this storage, this should never happen
974  if ($this->getUid() != $targetFolder->getStorage()->getUid()) {
975  throw new Exception('The operation of the folder cannot be called by this storage "' . $this->getUid() . '"', 1319550405);
976  }
977  // Check if user is allowed to copy
978  if (!$file->getStorage()->checkFileActionPermission('copy', $file)) {
979  throw new Exception\InsufficientFileReadPermissionsException('You are not allowed to copy the file "' . $file->getIdentifier() . '"', 1319550426);
980  }
981  // Check if targetFolder is writable
982  if (!$this->checkFolderActionPermission('write', $targetFolder)) {
983  throw new Exception\InsufficientFolderWritePermissionsException('You are not allowed to write to the target folder "' . $targetFolder->getIdentifier() . '"', 1319550435);
984  }
985  // Check for a valid file extension
986  if (!$this->checkFileExtensionPermission($targetFileName) || !$this->checkFileExtensionPermission($file->getName())) {
987  throw new Exception\IllegalFileExtensionException('You are not allowed to copy a file of that type.', 1319553317);
988  }
989  }
990 
1006  protected function assureFolderCopyPermissions(FolderInterface $folderToCopy, FolderInterface $targetParentFolder) {
1007  // Check if targetFolder is within this storage, this should never happen
1008  if ($this->getUid() !== $targetParentFolder->getStorage()->getUid()) {
1009  throw new Exception('The operation of the folder cannot be called by this storage "' . $this->getUid() . '"', 1377777624);
1010  }
1011  if (!$folderToCopy instanceof Folder) {
1012  throw new \RuntimeException('The folder "' . $folderToCopy->getIdentifier() . '" to copy is not of type Folder.', 1384209020);
1013  }
1014  // Check if user is allowed to copy and the folder is readable
1015  if (!$folderToCopy->getStorage()->checkFolderActionPermission('copy', $folderToCopy)) {
1016  throw new Exception\InsufficientFileReadPermissionsException('You are not allowed to copy the folder "' . $folderToCopy->getIdentifier() . '"', 1377777629);
1017  }
1018  if (!$targetParentFolder instanceof Folder) {
1019  throw new \RuntimeException('The target folder "' . $targetParentFolder->getIdentifier() . '" is not of type Folder.', 1384209021);
1020  }
1021  // Check if targetFolder is writable
1022  if (!$this->checkFolderActionPermission('write', $targetParentFolder)) {
1023  throw new Exception\InsufficientFolderWritePermissionsException('You are not allowed to write to the target folder "' . $targetParentFolder->getIdentifier() . '"', 1377777635);
1024  }
1025  }
1026 
1042  protected function assureFolderMovePermissions(FolderInterface $folderToMove, FolderInterface $targetParentFolder) {
1043  // Check if targetFolder is within this storage, this should never happen
1044  if ($this->getUid() !== $targetParentFolder->getStorage()->getUid()) {
1045  throw new \InvalidArgumentException('Cannot move a folder into a folder that does not belong to this storage.', 1325777289);
1046  }
1047  if (!$folderToMove instanceof Folder) {
1048  throw new \RuntimeException('The folder "' . $folderToMove->getIdentifier() . '" to move is not of type Folder.', 1384209022);
1049  }
1050  // Check if user is allowed to move and the folder is writable
1051  // In fact we would need to check if the parent folder of the folder to move is writable also
1052  // But as of now we cannot extract the parent folder from this folder
1053  if (!$folderToMove->getStorage()->checkFolderActionPermission('move', $folderToMove)) {
1054  throw new Exception\InsufficientFileReadPermissionsException('You are not allowed to copy the folder "' . $folderToMove->getIdentifier() . '"', 1377778045);
1055  }
1056  if (!$targetParentFolder instanceof Folder) {
1057  throw new \RuntimeException('The target folder "' . $targetParentFolder->getIdentifier() . '" is not of type Folder.', 1384209023);
1058  }
1059  // Check if targetFolder is writable
1060  if (!$this->checkFolderActionPermission('write', $targetParentFolder)) {
1061  throw new Exception\InsufficientFolderWritePermissionsException('You are not allowed to write to the target folder "' . $targetParentFolder->getIdentifier() . '"', 1377778049);
1062  }
1063  }
1064 
1065  /********************
1066  * FILE ACTIONS
1067  ********************/
1080  public function addFile($localFilePath, Folder $targetFolder, $targetFileName = '', $conflictMode = 'changeName') {
1081  $localFilePath = PathUtility::getCanonicalPath($localFilePath);
1082  // File is not available locally NOR is it an uploaded file
1083  if (!is_uploaded_file($localFilePath) && !file_exists($localFilePath)) {
1084  throw new \InvalidArgumentException('File "' . $localFilePath . '" does not exist.', 1319552745);
1085  }
1086  $targetFolder = $targetFolder ?: $this->getDefaultFolder();
1087  $targetFileName = $this->driver->sanitizeFileName($targetFileName ?: PathUtility::basename($localFilePath));
1088  $this->assureFileAddPermissions('', $targetFolder, $targetFileName);
1089 
1090  // We do not care whether the file exists yet because $targetFileName may be changed by an
1091  // external slot and only then we should check how to proceed according to $conflictMode
1092  $targetFileName = $this->emitPreFileAddSignal($targetFileName, $targetFolder, $localFilePath);
1093 
1094  if ($conflictMode === 'cancel' && $this->driver->fileExistsInFolder($targetFileName, $targetFolder->getIdentifier())) {
1095  throw new Exception\ExistingTargetFileNameException('File "' . $targetFileName . '" already exists in folder ' . $targetFolder->getIdentifier(), 1322121068);
1096  } elseif ($conflictMode === 'changeName') {
1097  $targetFileName = $this->getUniqueName($targetFolder, $targetFileName);
1098  }
1099 
1100  $fileIdentifier = $this->driver->addFile($localFilePath, $targetFolder->getIdentifier(), $targetFileName);
1101  $file = ResourceFactory::getInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $fileIdentifier);
1102 
1103  $this->emitPostFileAddSignal($file, $targetFolder);
1104 
1105  return $file;
1106  }
1107 
1118  public function updateProcessedFile($localFilePath, ProcessedFile $processedFile, Folder $processingFolder = NULL) {
1119  if (!file_exists($localFilePath)) {
1120  throw new \InvalidArgumentException('File "' . $localFilePath . '" does not exist.', 1319552746);
1121  }
1122  if ($processingFolder === NULL) {
1124  }
1125  $fileIdentifier = $this->driver->addFile($localFilePath, $processingFolder->getIdentifier(), $processedFile->getName());
1126 
1127  // @todo check if we have to update the processed file other then the identifier
1128  $processedFile->setIdentifier($fileIdentifier);
1129  return $processedFile;
1130  }
1131 
1139  public function hashFile(FileInterface $fileObject, $hash) {
1140  return $this->hashFileByIdentifier($fileObject->getIdentifier(), $hash);
1141  }
1142 
1151  public function hashFileByIdentifier($fileIdentifier, $hash) {
1152  return $this->driver->hash($fileIdentifier, $hash);
1153  }
1154 
1163  public function hashFileIdentifier($file) {
1164  if (is_object($file) && $file instanceof FileInterface) {
1166  $file = $file->getIdentifier();
1167  }
1168  return $this->driver->hashIdentifier($file);
1169  }
1170 
1181  public function getPublicUrl(ResourceInterface $resourceObject, $relativeToCurrentScript = FALSE) {
1182  $publicUrl = NULL;
1183  if ($this->isOnline()) {
1184  // Pre-process the public URL by an accordant slot
1185  $this->emitPreGeneratePublicUrlSignal($resourceObject, $relativeToCurrentScript, array('publicUrl' => &$publicUrl));
1186  // If slot did not handle the signal, use the default way to determine public URL
1187  if ($publicUrl === NULL) {
1188 
1189  if ($this->hasCapability(self::CAPABILITY_PUBLIC)) {
1190  $publicUrl = $this->driver->getPublicUrl($resourceObject->getIdentifier());
1191  }
1192 
1193  if ($publicUrl === NULL && $resourceObject instanceof FileInterface) {
1194  $queryParameterArray = array('eID' => 'dumpFile', 't' => '');
1195  if ($resourceObject instanceof File) {
1196  $queryParameterArray['f'] = $resourceObject->getUid();
1197  $queryParameterArray['t'] = 'f';
1198  } elseif ($resourceObject instanceof ProcessedFile) {
1199  $queryParameterArray['p'] = $resourceObject->getUid();
1200  $queryParameterArray['t'] = 'p';
1201  }
1202 
1203  $queryParameterArray['token'] = GeneralUtility::hmac(implode('|', $queryParameterArray), 'resourceStorageDumpFile');
1204  $publicUrl = 'index.php?' . str_replace('+', '%20', http_build_query($queryParameterArray));
1205  }
1206 
1207  // If requested, make the path relative to the current script in order to make it possible
1208  // to use the relative file
1209  if ($publicUrl !== NULL && $relativeToCurrentScript && !GeneralUtility::isValidUrl($publicUrl)) {
1210  $absolutePathToContainingFolder = PathUtility::dirname(PATH_site . $publicUrl);
1211  $pathPart = PathUtility::getRelativePathTo($absolutePathToContainingFolder);
1212  $filePart = substr(PATH_site . $publicUrl, strlen($absolutePathToContainingFolder) + 1);
1213  $publicUrl = $pathPart . $filePart;
1214  }
1215  }
1216  }
1217  return $publicUrl;
1218  }
1219 
1230  public function processFile(FileInterface $fileObject, $context, array $configuration) {
1231  if ($fileObject->getStorage() !== $this) {
1232  throw new \InvalidArgumentException('Cannot process files of foreign storage', 1353401835);
1233  }
1234  $processedFile = $this->getFileProcessingService()->processFile($fileObject, $this, $context, $configuration);
1235 
1236  return $processedFile;
1237  }
1238 
1246  public function getFileForLocalProcessing(FileInterface $fileObject, $writable = TRUE) {
1247  $filePath = $this->driver->getFileForLocalProcessing($fileObject->getIdentifier(), $writable);
1248  return $filePath;
1249  }
1250 
1257  public function getFile($identifier) {
1258  $file = $this->getFileFactory()->getFileObjectByStorageAndIdentifier($this->getUid(), $identifier);
1259  if (!$this->driver->fileExists($identifier)) {
1260  $file->setMissing(TRUE);
1261  }
1262  return $file;
1263  }
1264 
1272  public function getFileInfo(FileInterface $fileObject) {
1273  return $this->getFileInfoByIdentifier($fileObject->getIdentifier());
1274  }
1275 
1284  public function getFileInfoByIdentifier($identifier, array $propertiesToExtract = array()) {
1285  return $this->driver->getFileInfoByIdentifier($identifier, $propertiesToExtract);
1286  }
1287 
1293  public function unsetFileAndFolderNameFilters() {
1294  $this->fileAndFolderNameFilters = array();
1295  }
1296 
1303  $this->fileAndFolderNameFilters = $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['defaultFilterCallbacks'];
1304  }
1305 
1311  public function getFileAndFolderNameFilters() {
1313  }
1314 
1319  public function setFileAndFolderNameFilters(array $filters) {
1320  $this->fileAndFolderNameFilters = $filters;
1321  return $this;
1322  }
1323 
1327  public function addFileAndFolderNameFilter($filter) {
1328  $this->fileAndFolderNameFilters[] = $filter;
1329  }
1330 
1336  public function getFolderIdentifierFromFileIdentifier($fileIdentifier) {
1337  return $this->driver->getParentFolderIdentifierOfIdentifier($fileIdentifier);
1338  }
1339 
1353  public function getFileList($path, $start = 0, $numberOfItems = 0, $useFilters = TRUE, $loadIndexRecords = TRUE, $recursive = FALSE) {
1355  return $this->getFilesInFolder($this->getFolder($path), $start, $numberOfItems, $useFilters, $recursive);
1356  }
1357 
1366  public function getFilesInFolder(Folder $folder, $start = 0, $maxNumberOfItems = 0, $useFilters = TRUE, $recursive = FALSE) {
1367  $this->assureFolderReadPermission($folder);
1368 
1369  $rows = $this->getFileIndexRepository()->findByFolder($folder);
1370 
1371  $filters = $useFilters == TRUE ? $this->fileAndFolderNameFilters : array();
1372  $fileIdentifiers = array_values($this->driver->getFilesInFolder($folder->getIdentifier(), $start, $maxNumberOfItems, $recursive, $filters));
1373  $fileIdentifiersCount = count($fileIdentifiers);
1374  $items = array();
1375  if ($maxNumberOfItems === 0) {
1376  $maxNumberOfItems = $fileIdentifiersCount;
1377  }
1378  $end = min($fileIdentifiersCount, $start + $maxNumberOfItems);
1379  for ($i = $start; $i < $end; $i++) {
1380  $identifier = $fileIdentifiers[$i];
1381  if (isset($rows[$identifier])) {
1382  $fileObject = $this->getFileFactory()->getFileObject($rows[$identifier]['uid'], $rows[$identifier]);
1383  } else {
1384  $fileObject = $this->getFileFactory()->getFileObjectByStorageAndIdentifier($this->getUid(), $identifier);
1385  }
1386  if ($fileObject instanceof FileInterface) {
1387  $key = $fileObject->getName();
1388  while (isset($items[$key])) {
1389  $key .= 'z';
1390  }
1391  $items[$key] = $fileObject;
1392  }
1393  }
1394  uksort($items, 'strnatcasecmp');
1395 
1396  return $items;
1397  }
1398 
1406  public function getFileIdentifiersInFolder($folderIdentifier, $useFilters = TRUE, $recursive = FALSE) {
1407  $filters = $useFilters == TRUE ? $this->fileAndFolderNameFilters : array();
1408  return $this->driver->getFilesInFolder($folderIdentifier, 0, 0, $recursive, $filters);
1409  }
1410 
1418  public function getFolderIdentifiersInFolder($folderIdentifier, $useFilters = TRUE, $recursive = FALSE) {
1419  $filters = $useFilters == TRUE ? $this->fileAndFolderNameFilters : array();
1420  return $this->driver->getFoldersInFolder($folderIdentifier, 0, 0, $recursive, $filters);
1421  }
1422 
1429  public function hasFile($identifier) {
1430  // Allow if identifier is in processing folder
1431  if (!$this->isWithinProcessingFolder($identifier)) {
1432  $this->assureFolderReadPermission();
1433  }
1434  return $this->driver->fileExists($identifier);
1435  }
1436 
1442  public function getProcessingFolders() {
1443  if ($this->processingFolders === NULL) {
1444  $this->processingFolders = array();
1445  $this->processingFolders[] = $this->getProcessingFolder();
1447  $storageRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
1448  $allStorages = $storageRepository->findAll();
1449  foreach ($allStorages as $storage) {
1450  // To circumvent the permission check of the folder, we use the factory to create it "manually" instead of directly using $storage->getProcessingFolder()
1451  // See #66695 for details
1452  $storageRecord = $storage->getStorageRecord();
1453  list($storageUid, $processingFolderIdentifier) = GeneralUtility::trimExplode(':', $storageRecord['processingfolder']);
1454  if (empty($processingFolderIdentifier) || (int)$storageUid !== $this->getUid()) {
1455  continue;
1456  }
1457  $potentialProcessingFolder = ResourceFactory::getInstance()->getInstance()->createFolderObject($this, $processingFolderIdentifier, $processingFolderIdentifier);
1458  if ($potentialProcessingFolder->getStorage() === $this && $potentialProcessingFolder->getIdentifier() !== $this->getProcessingFolder()->getIdentifier()) {
1459  $this->processingFolders[] = $potentialProcessingFolder;
1460  }
1461  }
1462  }
1463 
1464  return $this->processingFolders;
1465  }
1466 
1474  public function isProcessingFolder(Folder $folder) {
1475  $isProcessingFolder = FALSE;
1476  foreach ($this->getProcessingFolders() as $processingFolder) {
1477  if ($folder->getCombinedIdentifier() === $processingFolder->getCombinedIdentifier()) {
1478  $isProcessingFolder = TRUE;
1479  break;
1480  }
1481  }
1482  return $isProcessingFolder;
1483  }
1484 
1492  public function hasFileInFolder($fileName, Folder $folder) {
1493  $this->assureFolderReadPermission($folder);
1494  return $this->driver->fileExistsInFolder($fileName, $folder->getIdentifier());
1495  }
1496 
1505  public function getFileContents($file) {
1506  $this->assureFileReadPermission($file);
1507  return $this->driver->getFileContents($file->getIdentifier());
1508  }
1509 
1519  public function dumpFileContents(FileInterface $file, $asDownload = FALSE, $alternativeFilename = NULL) {
1520  $downloadName = $alternativeFilename ?: $file->getName();
1521  $contentDisposition = $asDownload ? 'attachment' : 'inline';
1522  header('Content-Disposition: ' . $contentDisposition . '; filename="' . $downloadName . '"');
1523  header('Content-Type: ' . $file->getMimeType());
1524  header('Content-Length: ' . $file->getSize());
1525 
1526  // Cache-Control header is needed here to solve an issue with browser IE8 and lower
1527  // See for more information: http://support.microsoft.com/kb/323308
1528  header("Cache-Control: ''");
1529  header('Last-Modified: ' .
1530  gmdate('D, d M Y H:i:s', array_pop($this->driver->getFileInfoByIdentifier($file->getIdentifier(), array('mtime')))) . ' GMT',
1531  TRUE,
1532  200
1533  );
1534  ob_clean();
1535  flush();
1536  while (ob_get_level() > 0) {
1537  ob_end_clean();
1538  }
1539  $this->driver->dumpFileContents($file->getIdentifier());
1540  }
1541 
1553  public function setFileContents(AbstractFile $file, $contents) {
1554  // Check if user is allowed to edit
1555  $this->assureFileWritePermissions($file);
1556  // Call driver method to update the file and update file index entry afterwards
1557  $result = $this->driver->setFileContents($file->getIdentifier(), $contents);
1558  $this->getIndexer()->updateIndexEntry($file);
1559  $this->emitPostFileSetContentsSignal($file, $contents);
1560  return $result;
1561  }
1562 
1575  public function createFile($fileName, Folder $targetFolderObject) {
1576  $this->assureFileAddPermissions('', $targetFolderObject, $fileName);
1577  $newFileIdentifier = $this->driver->createFile($fileName, $targetFolderObject->getIdentifier());
1578  $this->emitPostFileCreateSignal($newFileIdentifier, $targetFolderObject);
1579  return ResourceFactory::getInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $newFileIdentifier);
1580  }
1581 
1590  public function deleteFile($fileObject) {
1591  $this->assureFileDeletePermissions($fileObject);
1592 
1593  $this->emitPreFileDeleteSignal($fileObject);
1594 
1595  if ($this->driver->fileExists($fileObject->getIdentifier())) {
1596  $result = $this->driver->deleteFile($fileObject->getIdentifier());
1597  if (!$result) {
1598  throw new Exception\FileOperationErrorException('Deleting the file "' . $fileObject->getIdentifier() . '\' failed.', 1329831691);
1599  }
1600  }
1601  // Mark the file object as deleted
1602  if ($fileObject instanceof File) {
1603  $fileObject->setDeleted();
1604  }
1605 
1606  $this->emitPostFileDeleteSignal($fileObject);
1607 
1608  return TRUE;
1609  }
1610 
1625  public function copyFile(FileInterface $file, Folder $targetFolder, $targetFileName = NULL, $conflictMode = 'renameNewFile') {
1626  if ($targetFileName === NULL) {
1627  $targetFileName = $file->getName();
1628  }
1629  $sanitizedTargetFileName = $this->driver->sanitizeFileName($targetFileName);
1630  $this->assureFileCopyPermissions($file, $targetFolder, $sanitizedTargetFileName);
1631  $this->emitPreFileCopySignal($file, $targetFolder);
1632  // File exists and we should abort, let's abort
1633  if ($conflictMode === 'cancel' && $targetFolder->hasFile($sanitizedTargetFileName)) {
1634  throw new Exception\ExistingTargetFileNameException('The target file already exists.', 1320291064);
1635  }
1636  // File exists and we should find another name, let's find another one
1637  if ($conflictMode === 'renameNewFile' && $targetFolder->hasFile($sanitizedTargetFileName)) {
1638  $sanitizedTargetFileName = $this->getUniqueName($targetFolder, $sanitizedTargetFileName);
1639  }
1640  $sourceStorage = $file->getStorage();
1641  // Call driver method to create a new file from an existing file object,
1642  // and return the new file object
1643  if ($sourceStorage === $this) {
1644  $newFileObjectIdentifier = $this->driver->copyFileWithinStorage($file->getIdentifier(), $targetFolder->getIdentifier(), $sanitizedTargetFileName);
1645  } else {
1646  $tempPath = $file->getForLocalProcessing();
1647  $newFileObjectIdentifier = $this->driver->addFile($tempPath, $targetFolder->getIdentifier(), $sanitizedTargetFileName);
1648  }
1649  $newFileObject = ResourceFactory::getInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $newFileObjectIdentifier);
1650  $this->emitPostFileCopySignal($file, $targetFolder);
1651  return $newFileObject;
1652  }
1653 
1669  public function moveFile($file, $targetFolder, $targetFileName = NULL, $conflictMode = 'renameNewFile') {
1670  if ($targetFileName === NULL) {
1671  $targetFileName = $file->getName();
1672  }
1673  $originalFolder = $file->getParentFolder();
1674  $sanitizedTargetFileName = $this->driver->sanitizeFileName($targetFileName);
1675  $this->assureFileMovePermissions($file, $targetFolder, $sanitizedTargetFileName);
1676  if ($targetFolder->hasFile($sanitizedTargetFileName)) {
1677  // File exists and we should abort, let's abort
1678  if ($conflictMode === 'renameNewFile') {
1679  $sanitizedTargetFileName = $this->getUniqueName($targetFolder, $sanitizedTargetFileName);
1680  } elseif ($conflictMode === 'cancel') {
1681  throw new Exception\ExistingTargetFileNameException('The target file already exists', 1329850997);
1682  }
1683  }
1684  $this->emitPreFileMoveSignal($file, $targetFolder);
1685  $sourceStorage = $file->getStorage();
1686  // Call driver method to move the file and update the index entry
1687  try {
1688  if ($sourceStorage === $this) {
1689  $newIdentifier = $this->driver->moveFileWithinStorage($file->getIdentifier(), $targetFolder->getIdentifier(), $sanitizedTargetFileName);
1690  if (!$file instanceof AbstractFile) {
1691  throw new \RuntimeException('The given file is not of type AbstractFile.', 1384209025);
1692  }
1693  $file->updateProperties(array('identifier' => $newIdentifier));
1694  } else {
1695  $tempPath = $file->getForLocalProcessing();
1696  $newIdentifier = $this->driver->addFile($tempPath, $targetFolder->getIdentifier(), $sanitizedTargetFileName);
1697  $sourceStorage->driver->deleteFile($file->getIdentifier());
1698  if ($file instanceof File) {
1699  $file->updateProperties(array('storage' => $this->getUid(), 'identifier' => $newIdentifier));
1700  }
1701  }
1702  $this->getIndexer()->updateIndexEntry($file);
1703  } catch (\TYPO3\CMS\Core\Exception $e) {
1704  echo $e->getMessage();
1705  }
1706  $this->emitPostFileMoveSignal($file, $targetFolder, $originalFolder);
1707  return $file;
1708  }
1709 
1721  public function renameFile($file, $targetFileName) {
1722  // TODO add $conflictMode setting
1723 
1724  // The name should be different from the current.
1725  if ($file->getName() === $targetFileName) {
1726  return $file;
1727  }
1728  $sanitizedTargetFileName = $this->driver->sanitizeFileName($targetFileName);
1729  $this->assureFileRenamePermissions($file, $sanitizedTargetFileName);
1730  $this->emitPreFileRenameSignal($file, $sanitizedTargetFileName);
1731 
1732  // Call driver method to rename the file and update the index entry
1733  try {
1734  $newIdentifier = $this->driver->renameFile($file->getIdentifier(), $sanitizedTargetFileName);
1735  if ($file instanceof File) {
1736  $file->updateProperties(array('identifier' => $newIdentifier));
1737  }
1738  $this->getIndexer()->updateIndexEntry($file);
1739  } catch (\RuntimeException $e) {
1740 
1741  }
1742 
1743  $this->emitPostFileRenameSignal($file, $sanitizedTargetFileName);
1744 
1745  return $file;
1746  }
1747 
1759  public function replaceFile(FileInterface $file, $localFilePath) {
1760  $this->assureFileWritePermissions($file);
1761  if (!file_exists($localFilePath)) {
1762  throw new \InvalidArgumentException('File "' . $localFilePath . '" does not exist.', 1325842622);
1763  }
1764  $this->emitPreFileReplaceSignal($file, $localFilePath);
1765  $result = $this->driver->replaceFile($file->getIdentifier(), $localFilePath);
1766  if ($file instanceof File) {
1767  $this->getIndexer()->updateIndexEntry($file);
1768  }
1769  $this->emitPostFileReplaceSignal($file, $localFilePath);
1770  return $result;
1771  }
1772 
1782  public function addUploadedFile(array $uploadedFileData, Folder $targetFolder = NULL, $targetFileName = NULL, $conflictMode = 'cancel') {
1783  $localFilePath = $uploadedFileData['tmp_name'];
1784  if ($targetFolder === NULL) {
1785  $targetFolder = $this->getDefaultFolder();
1786  }
1787  if ($targetFileName === NULL) {
1788  $targetFileName = $uploadedFileData['name'];
1789  }
1790  // Handling $conflictMode is delegated to addFile()
1791  $this->assureFileUploadPermissions($localFilePath, $targetFolder, $targetFileName, $uploadedFileData['size']);
1792  $resultObject = $this->addFile($localFilePath, $targetFolder, $targetFileName, $conflictMode);
1793  return $resultObject;
1794  }
1795 
1796  /********************
1797  * FOLDER ACTIONS
1798  ********************/
1805  protected function getAllFileObjectsInFolder(Folder $folder) {
1806  $files = array();
1807  $folderQueue = array($folder);
1808  while (!empty($folderQueue)) {
1809  $folder = array_shift($folderQueue);
1810  foreach ($folder->getSubfolders() as $subfolder) {
1811  $folderQueue[] = $subfolder;
1812  }
1813  foreach ($folder->getFiles() as $file) {
1815  $files[$file->getIdentifier()] = $file;
1816  }
1817  }
1818 
1819  return $files;
1820  }
1821 
1836  public function moveFolder(Folder $folderToMove, Folder $targetParentFolder, $newFolderName = NULL, $conflictMode = 'renameNewFolder') {
1837  // TODO add tests
1838  $originalFolder = $folderToMove->getParentFolder();
1839  $this->assureFolderMovePermissions($folderToMove, $targetParentFolder);
1840  $sourceStorage = $folderToMove->getStorage();
1841  $returnObject = NULL;
1842  $sanitizedNewFolderName = $this->driver->sanitizeFileName($newFolderName ?: $folderToMove->getName());
1843  // TODO check if folder already exists in $targetParentFolder, handle this conflict then
1844  $this->emitPreFolderMoveSignal($folderToMove, $targetParentFolder, $sanitizedNewFolderName);
1845  // Get all file objects now so we are able to update them after moving the folder
1846  $fileObjects = $this->getAllFileObjectsInFolder($folderToMove);
1847  if ($sourceStorage === $this) {
1848  if ($this->isWithinFolder($folderToMove, $targetParentFolder)) {
1849  throw new InvalidTargetFolderException(
1850  sprintf(
1851  'Cannot move folder "%s" into target folder "%s", because the target folder is already within the folder to be moved!',
1852  $folderToMove->getName(),
1853  $targetParentFolder->getName()
1854  ),
1855  1422723050
1856  );
1857  }
1858  $fileMappings = $this->driver->moveFolderWithinStorage($folderToMove->getIdentifier(), $targetParentFolder->getIdentifier(), $sanitizedNewFolderName);
1859  } else {
1860  $fileMappings = $this->moveFolderBetweenStorages($folderToMove, $targetParentFolder, $sanitizedNewFolderName);
1861  }
1862  // Update the identifier and storage of all file objects
1863  foreach ($fileObjects as $oldIdentifier => $fileObject) {
1864  $newIdentifier = $fileMappings[$oldIdentifier];
1865  $fileObject->updateProperties(array('storage' => $this->getUid(), 'identifier' => $newIdentifier));
1866  $this->getIndexer()->updateIndexEntry($fileObject);
1867  }
1868  $returnObject = $this->getFolder($fileMappings[$folderToMove->getIdentifier()]);
1869  $this->emitPostFolderMoveSignal($folderToMove, $targetParentFolder, $returnObject->getName(), $originalFolder);
1870  return $returnObject;
1871  }
1872 
1883  protected function moveFolderBetweenStorages(Folder $folderToMove, Folder $targetParentFolder, $newFolderName) {
1884  throw new \RuntimeException('Not yet implemented');
1885  }
1886 
1897  public function copyFolder(FolderInterface $folderToCopy, FolderInterface $targetParentFolder, $newFolderName = NULL, $conflictMode = 'renameNewFolder') {
1898  // TODO implement the $conflictMode handling
1899  $this->assureFolderCopyPermissions($folderToCopy, $targetParentFolder);
1900  $returnObject = NULL;
1901  $sanitizedNewFolderName = $this->driver->sanitizeFileName($newFolderName ?: $folderToCopy->getName());
1902  if ($folderToCopy instanceof Folder && $targetParentFolder instanceof Folder) {
1903  $this->emitPreFolderCopySignal($folderToCopy, $targetParentFolder, $sanitizedNewFolderName);
1904  }
1905  $sourceStorage = $folderToCopy->getStorage();
1906  // call driver method to move the file
1907  // that also updates the file object properties
1908  if ($sourceStorage === $this) {
1909  if ($this->isWithinFolder($folderToCopy, $targetParentFolder)) {
1910  throw new InvalidTargetFolderException(
1911  sprintf(
1912  'Cannot copy folder "%s" into target folder "%s", because the target folder is already within the folder to be copied!',
1913  $folderToCopy->getName(),
1914  $targetParentFolder->getName()
1915  ),
1916  1422723059
1917  );
1918  }
1919  $this->driver->copyFolderWithinStorage($folderToCopy->getIdentifier(), $targetParentFolder->getIdentifier(), $sanitizedNewFolderName);
1920  $returnObject = $this->getFolder($targetParentFolder->getSubfolder($sanitizedNewFolderName)->getIdentifier());
1921  } else {
1922  $this->copyFolderBetweenStorages($folderToCopy, $targetParentFolder, $sanitizedNewFolderName);
1923  }
1924  $this->emitPostFolderCopySignal($folderToCopy, $targetParentFolder, $returnObject->getName());
1925  return $returnObject;
1926  }
1927 
1938  protected function copyFolderBetweenStorages(Folder $folderToCopy, Folder $targetParentFolder, $newFolderName) {
1939  throw new \RuntimeException('Not yet implemented.');
1940  }
1941 
1951  public function renameFolder($folderObject, $newName) {
1952 
1953  // Renaming the folder should check if the parent folder is writable
1954  // We cannot do this however because we cannot extract the parent folder from a folder currently
1955  if (!$this->checkFolderActionPermission('rename', $folderObject)) {
1956  throw new Exception\InsufficientUserPermissionsException('You are not allowed to rename the folder "' . $folderObject->getIdentifier() . '\'', 1357811441);
1957  }
1958 
1959  $sanitizedNewName = $this->driver->sanitizeFileName($newName);
1960  $returnObject = NULL;
1961  if ($this->driver->folderExistsInFolder($sanitizedNewName, $folderObject->getIdentifier())) {
1962  throw new \InvalidArgumentException('The folder ' . $sanitizedNewName . ' already exists in folder ' . $folderObject->getIdentifier(), 1325418870);
1963  }
1964 
1965  $this->emitPreFolderRenameSignal($folderObject, $sanitizedNewName);
1966 
1967  $fileObjects = $this->getAllFileObjectsInFolder($folderObject);
1968  $fileMappings = $this->driver->renameFolder($folderObject->getIdentifier(), $sanitizedNewName);
1969  // Update the identifier of all file objects
1970  foreach ($fileObjects as $oldIdentifier => $fileObject) {
1971  $newIdentifier = $fileMappings[$oldIdentifier];
1972  $fileObject->updateProperties(array('identifier' => $newIdentifier));
1973  $this->getIndexer()->updateIndexEntry($fileObject);
1974  }
1975  $returnObject = $this->getFolder($fileMappings[$folderObject->getIdentifier()]);
1976 
1977  $this->emitPostFolderRenameSignal($folderObject, $returnObject->getName());
1978 
1979  return $returnObject;
1980  }
1981 
1994  public function deleteFolder($folderObject, $deleteRecursively = FALSE) {
1995  $isEmpty = $this->driver->isFolderEmpty($folderObject->getIdentifier());
1996  $this->assureFolderDeletePermission($folderObject, ($deleteRecursively && !$isEmpty));
1997  if (!$isEmpty && !$deleteRecursively) {
1998  throw new \RuntimeException('Could not delete folder "' . $folderObject->getIdentifier() . '" because it is not empty.', 1325952534);
1999  }
2000 
2001  $this->emitPreFolderDeleteSignal($folderObject);
2002 
2003  foreach ($this->getFilesInFolder($folderObject, 0, 0, FALSE, $deleteRecursively) as $file) {
2004  $this->deleteFile($file);
2005  }
2006 
2007  $result = $this->driver->deleteFolder($folderObject->getIdentifier(), $deleteRecursively);
2008 
2009  $this->emitPostFolderDeleteSignal($folderObject);
2010 
2011  return $result;
2012  }
2013 
2024  public function getFolderList($path, $start = 0, $numberOfItems = 0, $useFilters = TRUE) {
2026  // Permissions are checked in $this->fetchFolderListFromDriver()
2027  $filters = $useFilters === TRUE ? $this->fileAndFolderNameFilters : array();
2028  return $this->fetchFolderListFromDriver($path, $start, $numberOfItems, $filters);
2029  }
2030 
2040  public function getFoldersInFolder(Folder $folder, $start = 0, $maxNumberOfItems = 0, $useFilters = TRUE, $recursive = FALSE) {
2041  $filters = $useFilters == TRUE ? $this->fileAndFolderNameFilters : array();
2042  $folderIdentifiers = $this->driver->getFoldersInFolder($folder->getIdentifier(), $start, $maxNumberOfItems, $recursive, $filters);
2043 
2044  // Exclude processing folders
2045  foreach ($this->getProcessingFolders() as $processingFolder) {
2046  $processingIdentifier = $processingFolder->getIdentifier();
2047  if (isset($folderIdentifiers[$processingIdentifier])) {
2048  unset($folderIdentifiers[$processingIdentifier]);
2049  }
2050  }
2051  $folders = array();
2052  foreach ($folderIdentifiers as $folderIdentifier) {
2053  $folders[$folderIdentifier] = $this->getFolder($folderIdentifier, TRUE);
2054  }
2055  return $folders;
2056  }
2057 
2067  public function fetchFolderListFromDriver($path, $start = 0, $numberOfItems = 0, array $folderFilterCallbacks = array(), $recursive = FALSE) {
2069  // This also checks for access to that path and throws exceptions accordingly
2070  $parentFolder = $this->getFolder($path);
2071  if ($parentFolder === NULL) {
2072  return array();
2073  }
2074  $folders = $this->getFoldersInFolder($parentFolder, $start, $numberOfItems, count($folderFilterCallbacks) > 0, $recursive);
2075  $folderInfo = array();
2076  foreach ($folders as $folder) {
2077  $folderInfo[$folder->getIdentifier()] = array(
2078  'name' => $folder->getName(),
2079  'identifier' => $folder->getIdentifier()
2080  );
2081  }
2082  return $folderInfo;
2083  }
2084 
2091  public function hasFolder($identifier) {
2092  $this->assureFolderReadPermission();
2093  return $this->driver->folderExists($identifier);
2094  }
2095 
2103  public function hasFolderInFolder($folderName, Folder $folder) {
2104  $this->assureFolderReadPermission($folder);
2105  return $this->driver->folderExistsInFolder($folderName, $folder->getIdentifier());
2106  }
2107 
2120  public function createFolder($folderName, Folder $parentFolder = NULL) {
2121  if ($parentFolder === NULL) {
2122  $parentFolder = $this->getRootLevelFolder();
2123  } elseif (!$this->driver->folderExists($parentFolder->getIdentifier())) {
2124  throw new \InvalidArgumentException('Parent folder "' . $parentFolder->getIdentifier() . '" does not exist.', 1325689164);
2125  }
2126  if (!$this->checkFolderActionPermission('add', $parentFolder)) {
2127  throw new Exception\InsufficientFolderWritePermissionsException('You are not allowed to create directories in the folder "' . $parentFolder->getIdentifier() . '"', 1323059807);
2128  }
2129 
2130  $this->emitPreFolderAddSignal($parentFolder, $folderName);
2131 
2132  $newFolder = $this->getDriver()->createFolder($folderName, $parentFolder->getIdentifier(), TRUE);
2133  $newFolder = $this->getFolder($newFolder);
2134 
2135  $this->emitPostFolderAddSignal($newFolder);
2136 
2137  return $newFolder;
2138  }
2139 
2145  public function getDefaultFolder() {
2146  return $this->getFolder($this->driver->getDefaultFolder());
2147  }
2148 
2157  public function getFolder($identifier, $returnInaccessibleFolderObject = FALSE) {
2158 
2159  $data = $this->driver->getFolderInfoByIdentifier($identifier);
2160  $folder = ResourceFactory::getInstance()->createFolderObject($this, $data['identifier'], $data['name']);
2161 
2162  try {
2163  $this->assureFolderReadPermission($folder);
2164  } catch (Exception\InsufficientFolderAccessPermissionsException $e) {
2165  $folder = NULL;
2166  if ($returnInaccessibleFolderObject) {
2167  // if parent folder is readable return inaccessible folder object
2168  $parentPermissions = $this->driver->getPermissions($this->driver->getParentFolderIdentifierOfIdentifier($identifier));
2169  if ($parentPermissions['r']) {
2170  $folder = GeneralUtility::makeInstance(
2171  'TYPO3\\CMS\\Core\\Resource\\InaccessibleFolder', $this, $data['identifier'], $data['name']
2172  );
2173  }
2174  }
2175 
2176  if ($folder === NULL) {
2177  throw $e;
2178  }
2179  }
2180  return $folder;
2181  }
2182 
2189  public function isWithinProcessingFolder($identifier) {
2190  $inProcessingFolder = FALSE;
2191  foreach ($this->getProcessingFolders() as $processingFolder) {
2192  if ($this->driver->isWithin($processingFolder->getIdentifier(), $identifier)) {
2193  $inProcessingFolder = TRUE;
2194  break;
2195  }
2196  }
2197  return $inProcessingFolder;
2198  }
2199 
2208  public function isWithinFolder(Folder $folder, ResourceInterface $resource) {
2209  if ($folder->getStorage() !== $this) {
2210  throw new \InvalidArgumentException('Given folder "' . $folder->getIdentifier() . '" is not part of this storage!', 1422709241);
2211  }
2212  if ($folder->getStorage() !== $resource->getStorage()) {
2213  return FALSE;
2214  }
2215  return $this->driver->isWithin($folder->getIdentifier(), $resource->getIdentifier());
2216  }
2217 
2226  public function getRootLevelFolder($respectFileMounts = TRUE) {
2227  if ($respectFileMounts && count($this->fileMounts)) {
2228  $mount = reset($this->fileMounts);
2229  return $mount['folder'];
2230  } else {
2231  return ResourceFactory::getInstance()->createFolderObject($this, $this->driver->getRootLevelFolder(), '');
2232  }
2233  }
2234 
2243  protected function emitPreFileAddSignal($targetFileName, Folder $targetFolder, $sourceFilePath) {
2244  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFileAdd, array(&$targetFileName, $targetFolder, $sourceFilePath, $this, $this->driver));
2245  return $targetFileName;
2246  }
2247 
2255  protected function emitPostFileAddSignal(FileInterface $file, Folder $targetFolder) {
2256  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileAdd, array($file, $targetFolder));
2257  }
2258 
2266  protected function emitPreFileCopySignal(FileInterface $file, Folder $targetFolder) {
2267  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFileCopy, array($file, $targetFolder));
2268  }
2269 
2277  protected function emitPostFileCopySignal(FileInterface $file, Folder $targetFolder) {
2278  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileCopy, array($file, $targetFolder));
2279  }
2280 
2288  protected function emitPreFileMoveSignal(FileInterface $file, Folder $targetFolder) {
2289  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFileMove, array($file, $targetFolder));
2290  }
2291 
2300  protected function emitPostFileMoveSignal(FileInterface $file, Folder $targetFolder, Folder $originalFolder) {
2301  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileMove, array($file, $targetFolder, $originalFolder));
2302  }
2303 
2311  protected function emitPreFileRenameSignal(FileInterface $file, $targetFolder) {
2312  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFileRename, array($file, $targetFolder));
2313  }
2314 
2322  protected function emitPostFileRenameSignal(FileInterface $file, $targetFolder) {
2323  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileRename, array($file, $targetFolder));
2324  }
2325 
2333  protected function emitPreFileReplaceSignal(FileInterface $file, $localFilePath) {
2334  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFileReplace, array($file, $localFilePath));
2335  }
2336 
2344  protected function emitPostFileReplaceSignal(FileInterface $file, $localFilePath) {
2345  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileReplace, array($file, $localFilePath));
2346  }
2347 
2354  protected function emitPostFileCreateSignal($newFileIdentifier, Folder $targetFolder) {
2355  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileCreate, array($newFileIdentifier, $targetFolder));
2356  }
2357 
2364  protected function emitPreFileDeleteSignal(FileInterface $file) {
2365  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFileDelete, array($file));
2366  }
2367 
2374  protected function emitPostFileDeleteSignal(FileInterface $file) {
2375  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileDelete, array($file));
2376  }
2377 
2385  protected function emitPostFileSetContentsSignal(FileInterface $file, $content) {
2386  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFileSetContents, array($file, $content));
2387  }
2388 
2396  protected function emitPreFolderAddSignal(Folder $targetFolder, $name) {
2397  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFolderAdd, array($targetFolder, $name));
2398  }
2399 
2406  protected function emitPostFolderAddSignal(Folder $folder) {
2407  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFolderAdd, array($folder));
2408  }
2409 
2418  protected function emitPreFolderCopySignal(Folder $folder, Folder $targetFolder, $newName) {
2419  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFolderCopy, array($folder, $targetFolder, $newName));
2420  }
2421 
2430  protected function emitPostFolderCopySignal(Folder $folder, Folder $targetFolder, $newName) {
2431  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFolderCopy, array($folder, $targetFolder, $newName));
2432  }
2433 
2442  protected function emitPreFolderMoveSignal(Folder $folder, Folder $targetFolder, $newName) {
2443  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFolderMove, array($folder, $targetFolder, $newName));
2444  }
2445 
2455  protected function emitPostFolderMoveSignal(Folder $folder, Folder $targetFolder, $newName, Folder $originalFolder) {
2456  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFolderMove, array($folder, $targetFolder, $newName, $originalFolder));
2457  }
2458 
2466  protected function emitPreFolderRenameSignal(Folder $folder, $newName) {
2467  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFolderRename, array($folder, $newName));
2468  }
2469 
2477  protected function emitPostFolderRenameSignal(Folder $folder, $newName) {
2478  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFolderRename, array($folder, $newName));
2479  }
2480 
2487  protected function emitPreFolderDeleteSignal(Folder $folder) {
2488  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreFolderDelete, array($folder));
2489  }
2490 
2497  protected function emitPostFolderDeleteSignal(Folder $folder) {
2498  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PostFolderDelete, array($folder));
2499  }
2500 
2508  protected function emitPreGeneratePublicUrlSignal(ResourceInterface $resourceObject, $relativeToCurrentScript, array $urlData) {
2509  $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', self::SIGNAL_PreGeneratePublicUrl, array($this, $this->driver, $resourceObject, $relativeToCurrentScript, $urlData));
2510  }
2511 
2525  protected function getUniqueName(Folder $folder, $theFile, $dontCheckForUnique = FALSE) {
2526  static $maxNumber = 99, $uniqueNamePrefix = '';
2527  // Fetches info about path, name, extension of $theFile
2528  $origFileInfo = PathUtility::pathinfo($theFile);
2529  // Adds prefix
2530  if ($uniqueNamePrefix) {
2531  $origFileInfo['basename'] = $uniqueNamePrefix . $origFileInfo['basename'];
2532  $origFileInfo['filename'] = $uniqueNamePrefix . $origFileInfo['filename'];
2533  }
2534  // Check if the file exists and if not - return the fileName...
2535  // The destinations file
2536  $theDestFile = $origFileInfo['basename'];
2537  // If the file does NOT exist we return this fileName
2538  if (!$this->driver->fileExistsInFolder($theDestFile, $folder->getIdentifier()) || $dontCheckForUnique) {
2539  return $theDestFile;
2540  }
2541  // Well the fileName in its pure form existed. Now we try to append
2542  // numbers / unique-strings and see if we can find an available fileName
2543  // This removes _xx if appended to the file
2544  $theTempFileBody = preg_replace('/_[0-9][0-9]$/', '', $origFileInfo['filename']);
2545  $theOrigExt = $origFileInfo['extension'] ? '.' . $origFileInfo['extension'] : '';
2546  for ($a = 1; $a <= $maxNumber + 1; $a++) {
2547  // First we try to append numbers
2548  if ($a <= $maxNumber) {
2549  $insert = '_' . sprintf('%02d', $a);
2550  } else {
2551  $insert = '_' . substr(md5(uniqid('', TRUE)), 0, 6);
2552  }
2553  $theTestFile = $theTempFileBody . $insert . $theOrigExt;
2554  // The destinations file
2555  $theDestFile = $theTestFile;
2556  // If the file does NOT exist we return this fileName
2557  if (!$this->driver->fileExistsInFolder($theDestFile, $folder->getIdentifier())) {
2558  return $theDestFile;
2559  }
2560  }
2561  throw new \RuntimeException('Last possible name "' . $theDestFile . '" is already taken.', 1325194291);
2562  }
2563 
2569  protected function getSignalSlotDispatcher() {
2570  if (!isset($this->signalSlotDispatcher)) {
2571  $this->signalSlotDispatcher = $this->getObjectManager()->get('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
2572  }
2574  }
2575 
2581  protected function getObjectManager() {
2582  return GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
2583  }
2584 
2588  protected function getFileFactory() {
2589  return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
2590  }
2591 
2595  protected function getFileIndexRepository() {
2597  }
2598 
2602  protected function getFileProcessingService() {
2603  if (!$this->fileProcessingService) {
2604  $this->fileProcessingService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\FileProcessingService', $this, $this->driver);
2605  }
2607  }
2608 
2615  public function getRole(FolderInterface $folder) {
2616  $folderRole = FolderInterface::ROLE_DEFAULT;
2617  $identifier = $folder->getIdentifier();
2618  if (method_exists($this->driver, 'getRole')) {
2619  $folderRole = $this->driver->getRole($folder->getIdentifier());
2620  }
2621  if (isset($this->fileMounts[$identifier])) {
2622  $folderRole = FolderInterface::ROLE_MOUNT;
2623 
2624  if (!empty($this->fileMounts[$identifier]['read_only'])) {
2626  }
2627  if ($this->fileMounts[$identifier]['user_mount']) {
2628  $folderRole = FolderInterface::ROLE_USER_MOUNT;
2629  }
2630  }
2631  if ($folder instanceof Folder && $this->isProcessingFolder($folder)) {
2632  $folderRole = FolderInterface::ROLE_PROCESSING;
2633  }
2634 
2635  return $folderRole;
2636  }
2637 
2644  public function getProcessingFolder() {
2645  if (!isset($this->processingFolder)) {
2646  $processingFolder = self::DEFAULT_ProcessingFolder;
2647  if (!empty($this->storageRecord['processingfolder'])) {
2648  $processingFolder = $this->storageRecord['processingfolder'];
2649  }
2650  try {
2651  if (strpos($processingFolder, ':') !== FALSE) {
2652  list ($storageUid, $processingFolderIdentifier) = explode(':', $processingFolder, 2);
2653  $storage = ResourceFactory::getInstance()->getStorageObject($storageUid);
2654  if ($storage->hasFolder($processingFolderIdentifier)) {
2655  $this->processingFolder = $storage->getFolder($processingFolderIdentifier);
2656  } else {
2657  $this->processingFolder = $storage->createFolder(ltrim($processingFolderIdentifier, '/'));
2658  }
2659  } else {
2660  if ($this->driver->folderExists($processingFolder) === FALSE) {
2661  $this->processingFolder = $this->createFolder($processingFolder);
2662  } else {
2663  $data = $this->driver->getFolderInfoByIdentifier($processingFolder);
2664  $this->processingFolder = ResourceFactory::getInstance()->createFolderObject($this, $data['identifier'], $data['name']);
2665  }
2666  }
2667  } catch(Exception\InsufficientFolderWritePermissionsException $e) {
2668  $this->processingFolder = GeneralUtility::makeInstance(
2669  'TYPO3\\CMS\\Core\\Resource\\InaccessibleFolder', $this, $processingFolder, $processingFolder
2670  );
2671  } catch(Exception\ResourcePermissionsUnavailableException $e) {
2672  $this->processingFolder = GeneralUtility::makeInstance(
2673  'TYPO3\\CMS\\Core\\Resource\\InaccessibleFolder', $this, $processingFolder, $processingFolder
2674  );
2675  }
2676  }
2677  return $this->processingFolder;
2678  }
2679 
2685  public function getDriverType() {
2686  return $this->storageRecord['driver'];
2687  }
2688 
2694  protected function getIndexer() {
2695  return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Index\\Indexer', $this);
2696  }
2697 
2702  public function setDefault($isDefault) {
2703  $this->isDefault = (bool)$isDefault;
2704  }
2705 
2709  public function isDefault() {
2710  return $this->isDefault;
2711  }
2712 }
getFolderList($path, $start=0, $numberOfItems=0, $useFilters=TRUE)
assureFolderCopyPermissions(FolderInterface $folderToCopy, FolderInterface $targetParentFolder)
emitPreFileMoveSignal(FileInterface $file, Folder $targetFolder)
addFileMount($folderIdentifier, $additionalData=array())
replaceFile(FileInterface $file, $localFilePath)
checkFolderActionPermission($action, Folder $folder=NULL)
emitPreFileReplaceSignal(FileInterface $file, $localFilePath)
getFileList($path, $start=0, $numberOfItems=0, $useFilters=TRUE, $loadIndexRecords=TRUE, $recursive=FALSE)
isWithinFolder(Folder $folder, ResourceInterface $resource)
static uniqueList($in_list, $secondParameter=NULL)
moveFolder(Folder $folderToMove, Folder $targetParentFolder, $newFolderName=NULL, $conflictMode='renameNewFolder')
checkFileActionPermission($action, FileInterface $file)
setFileContents(AbstractFile $file, $contents)
hasFileInFolder($fileName, Folder $folder)
assureFileAddPermissions($localFilePath, $targetFolder, $targetFileName)
emitPreFolderMoveSignal(Folder $folder, Folder $targetFolder, $newName)
processFile(FileInterface $fileObject, $context, array $configuration)
static getRelativePathTo($targetPath)
Definition: PathUtility.php:31
emitPostFileRenameSignal(FileInterface $file, $targetFolder)
getSubfolders($start=0, $numberOfItems=0, $filterMode=self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS)
Definition: Folder.php:261
__construct(Driver\DriverInterface $driver, array $storageRecord)
emitPostFileCreateSignal($newFileIdentifier, Folder $targetFolder)
emitPreFileCopySignal(FileInterface $file, Folder $targetFolder)
hashFileByIdentifier($fileIdentifier, $hash)
getFilesInFolder(Folder $folder, $start=0, $maxNumberOfItems=0, $useFilters=TRUE, $recursive=FALSE)
getFolderIdentifiersInFolder($folderIdentifier, $useFilters=TRUE, $recursive=FALSE)
const TYPO3_MODE
Definition: init.php:40
getFolder($identifier, $returnInaccessibleFolderObject=FALSE)
emitPreFolderRenameSignal(Folder $folder, $newName)
emitPreFileRenameSignal(FileInterface $file, $targetFolder)
static getMaxUploadFileSize($localLimit=0)
getRootLevelFolder($respectFileMounts=TRUE)
static hmac($input, $additionalSecret='')
getPublicUrl(ResourceInterface $resourceObject, $relativeToCurrentScript=FALSE)
emitPostFolderRenameSignal(Folder $folder, $newName)
assureFolderMovePermissions(FolderInterface $folderToMove, FolderInterface $targetParentFolder)
setUserPermissions(array $userPermissions)
isWithinFileMountBoundaries($subject, $checkWriteAccess=FALSE)
addFile($localFilePath, Folder $targetFolder, $targetFileName='', $conflictMode='changeName')
emitPostFileReplaceSignal(FileInterface $file, $localFilePath)
static pathinfo($path, $options=NULL)
copyFolderBetweenStorages(Folder $folderToCopy, Folder $targetParentFolder, $newFolderName)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
copyFolder(FolderInterface $folderToCopy, FolderInterface $targetParentFolder, $newFolderName=NULL, $conflictMode='renameNewFolder')
static verifyFilenameAgainstDenyPattern($filename)
hashFile(FileInterface $fileObject, $hash)
emitPostFileSetContentsSignal(FileInterface $file, $content)
emitPostFileCopySignal(FileInterface $file, Folder $targetFolder)
emitPreGeneratePublicUrlSignal(ResourceInterface $resourceObject, $relativeToCurrentScript, array $urlData)
getFileForLocalProcessing(FileInterface $fileObject, $writable=TRUE)
assureFileCopyPermissions(FileInterface $file, Folder $targetFolder, $targetFileName)
moveFolderBetweenStorages(Folder $folderToMove, Folder $targetParentFolder, $newFolderName)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
assureFolderDeletePermission(Folder $folder, $checkDeleteRecursively)
emitPostFileAddSignal(FileInterface $file, Folder $targetFolder)
dumpFileContents(FileInterface $file, $asDownload=FALSE, $alternativeFilename=NULL)
createFolder($folderName, Folder $parentFolder=NULL)
deleteFolder($folderObject, $deleteRecursively=FALSE)
moveFile($file, $targetFolder, $targetFileName=NULL, $conflictMode='renameNewFile')
addUploadedFile(array $uploadedFileData, Folder $targetFolder=NULL, $targetFileName=NULL, $conflictMode='cancel')
fetchFolderListFromDriver($path, $start=0, $numberOfItems=0, array $folderFilterCallbacks=array(), $recursive=FALSE)
assureFileDeletePermissions(FileInterface $file)
setDriver(Driver\DriverInterface $driver)
emitPreFolderAddSignal(Folder $targetFolder, $name)
createFile($fileName, Folder $targetFolderObject)
emitPostFolderMoveSignal(Folder $folder, Folder $targetFolder, $newName, Folder $originalFolder)
assureFileUploadPermissions($localFilePath, $targetFolder, $targetFileName, $uploadedFileSize)
getUniqueName(Folder $folder, $theFile, $dontCheckForUnique=FALSE)
getFoldersInFolder(Folder $folder, $start=0, $maxNumberOfItems=0, $useFilters=TRUE, $recursive=FALSE)
emitPreFileAddSignal($targetFileName, Folder $targetFolder, $sourceFilePath)
emitPostFolderCopySignal(Folder $folder, Folder $targetFolder, $newName)
emitPreFolderCopySignal(Folder $folder, Folder $targetFolder, $newName)
hasFolderInFolder($folderName, Folder $folder)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
assureFileRenamePermissions(FileInterface $file, $targetFileName)
updateProcessedFile($localFilePath, ProcessedFile $processedFile, Folder $processingFolder=NULL)
getFileIdentifiersInFolder($folderIdentifier, $useFilters=TRUE, $recursive=FALSE)
assureFileMovePermissions(FileInterface $file, Folder $targetFolder, $targetFileName)
getFiles($start=0, $numberOfItems=0, $filterMode=self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive=FALSE)
Definition: Folder.php:206
emitPostFileMoveSignal(FileInterface $file, Folder $targetFolder, Folder $originalFolder)
getFileInfo(FileInterface $fileObject)
getFileInfoByIdentifier($identifier, array $propertiesToExtract=array())