/** * Unset all additional properties of test classes to help PHP * garbage collection. This reduces memory footprint with lots * of tests. * * If owerwriting tearDown() in test classes, please call * parent::tearDown() at the end. Unsetting of own properties * is not needed this way. * * @throws \RuntimeException * @return void */ protected function tearDown() { // Unset properties of test classes to safe memory $reflection = new \ReflectionObject($this); foreach ($reflection->getProperties() as $property) { $declaringClass = $property->getDeclaringClass()->getName(); if (!$property->isStatic() && $declaringClass !== \TYPO3\CMS\Core\Tests\UnitTestCase::class && $declaringClass !== \TYPO3\CMS\Core\Tests\BaseTestCase::class && strpos($property->getDeclaringClass()->getName(), 'PHPUnit_') !== 0) { $propertyName = $property->getName(); unset($this->{$propertyName}); } } unset($reflection); // Delete registered test files and directories foreach ($this->testFilesToDelete as $absoluteFileName) { $absoluteFileName = GeneralUtility::fixWindowsFilePath(PathUtility::getCanonicalPath($absoluteFileName)); if (!GeneralUtility::validPathStr($absoluteFileName)) { throw new \RuntimeException('tearDown() cleanup: Filename contains illegal characters', 1410633087); } if (!StringUtility::beginsWith($absoluteFileName, PATH_site . 'typo3temp/')) { throw new \RuntimeException('tearDown() cleanup: Files to delete must be within typo3temp/', 1410633412); } // file_exists returns false for links pointing to not existing targets, so handle links before next check. if (@is_link($absoluteFileName) || @is_file($absoluteFileName)) { unlink($absoluteFileName); } elseif (@is_dir($absoluteFileName)) { GeneralUtility::rmdir($absoluteFileName, true); } else { throw new \RuntimeException('tearDown() cleanup: File, link or directory does not exist', 1410633510); } } $this->testFilesToDelete = array(); }
/** * Makes sure the Path given as parameter is valid * * @param string $filePath The file path (including the file name!) * @return string * @throws InvalidPathException */ protected function canonicalizeAndCheckFilePath($filePath) { $filePath = PathUtility::getCanonicalPath($filePath); // filePath must be valid // Special case is required by vfsStream in Unit Test context if (!$this->isPathValid($filePath) && substr($filePath, 0, 6) !== 'vfs://') { throw new InvalidPathException('File ' . $filePath . ' is not valid (".." and "//" is not allowed in path).', 1320286857); } return $filePath; }
/** * Moves a file from the local filesystem to this storage. * * @param string $localFilePath The file on the server's hard disk to add * @param Folder $targetFolder The target folder where the file should be added * @param string $targetFileName The name of the file to be add, If not set, the local file name is used * @param string $conflictMode a value of the DuplicationBehavior enumeration * * @throws \InvalidArgumentException * @throws Exception\ExistingTargetFileNameException * @return FileInterface */ public function addFile($localFilePath, Folder $targetFolder, $targetFileName = '', $conflictMode = DuplicationBehavior::RENAME) { $localFilePath = PathUtility::getCanonicalPath($localFilePath); // File is not available locally NOR is it an uploaded file if (!is_uploaded_file($localFilePath) && !file_exists($localFilePath)) { throw new \InvalidArgumentException('File "' . $localFilePath . '" does not exist.', 1319552745); } $conflictMode = DuplicationBehavior::cast($conflictMode); $targetFolder = $targetFolder ?: $this->getDefaultFolder(); $targetFileName = $this->sanitizeFileName($targetFileName ?: PathUtility::basename($localFilePath), $targetFolder); $targetFileName = $this->emitPreFileAddSignal($targetFileName, $targetFolder, $localFilePath); $this->assureFileAddPermissions($targetFolder, $targetFileName); if ($conflictMode->equals(DuplicationBehavior::CANCEL) && $this->driver->fileExistsInFolder($targetFileName, $targetFolder->getIdentifier())) { throw new Exception\ExistingTargetFileNameException('File "' . $targetFileName . '" already exists in folder ' . $targetFolder->getIdentifier(), 1322121068); } elseif ($conflictMode->equals(DuplicationBehavior::RENAME)) { $targetFileName = $this->getUniqueName($targetFolder, $targetFileName); } $fileIdentifier = $this->driver->addFile($localFilePath, $targetFolder->getIdentifier(), $targetFileName); $file = ResourceFactory::getInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $fileIdentifier); if ($this->autoExtractMetadataEnabled()) { $indexer = GeneralUtility::makeInstance(Indexer::class, $this); $indexer->extractMetaData($file); } $this->emitPostFileAddSignal($file, $targetFolder); return $file; }
/** * Moves a file from the local filesystem to this storage. * * @param string $localFilePath The file on the server's hard disk to add. * @param Folder $targetFolder The target path, without the fileName * @param string $targetFileName The fileName. If not set, the local file name is used. * @param string $conflictMode possible value are 'cancel', 'replace', 'changeName' * * @throws \InvalidArgumentException * @throws Exception\ExistingTargetFileNameException * @return FileInterface */ public function addFile($localFilePath, Folder $targetFolder, $targetFileName = '', $conflictMode = 'changeName') { $localFilePath = PathUtility::getCanonicalPath($localFilePath); if (!file_exists($localFilePath)) { throw new \InvalidArgumentException('File "' . $localFilePath . '" does not exist.', 1319552745); } $targetFolder = $targetFolder ?: $this->getDefaultFolder(); $targetFileName = $this->driver->sanitizeFileName($targetFileName ?: PathUtility::basename($localFilePath)); $this->assureFileAddPermissions('', $targetFolder, $targetFileName); // We do not care whether the file exists yet because $targetFileName may be changed by an // external slot and only then we should check how to proceed according to $conflictMode $targetFileName = $this->emitPreFileAddSignal($targetFileName, $targetFolder, $localFilePath); if ($conflictMode === 'cancel' && $this->driver->fileExistsInFolder($targetFileName, $targetFolder->getIdentifier())) { throw new Exception\ExistingTargetFileNameException('File "' . $targetFileName . '" already exists in folder ' . $targetFolder->getIdentifier(), 1322121068); } elseif ($conflictMode === 'changeName') { $targetFileName = $this->getUniqueName($targetFolder, $targetFileName); } $fileIdentifier = $this->driver->addFile($localFilePath, $targetFolder->getIdentifier(), $targetFileName); $file = ResourceFactory::getInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $fileIdentifier); $this->emitPostFileAddSignal($file, $targetFolder); return $file; }
/** * Goes back in the path and checks in each directory if a folder named $this->recyclerFN (usually '_recycler_') is present. * If a folder in the tree happens to be a _recycler_-folder (which means that we're deleting something inside a _recycler_-folder) this is ignored * * @param string $theFile Takes a valid Path ($theFile) * @return string Returns the path (without trailing slash) of the closest recycle-folder if found. Else FALSE. * @todo To be put in Storage with a better concept * @todo Define visibility * @deprecated since TYPO3 6.0, use \TYPO3\CMS\Core\Resource\ResourceStorage method instead */ public function findRecycler($theFile) { GeneralUtility::logDeprecatedFunction(); if (GeneralUtility::validPathStr($theFile)) { $theFile = \TYPO3\CMS\Core\Utility\PathUtility::getCanonicalPath($theFile); $fI = GeneralUtility::split_fileref($theFile); $c = 0; // !!! Method has been put in the storage, can be saftely removed $rDir = $fI['path'] . $this->recyclerFN; while ($this->checkPathAgainstMounts($fI['path']) && $c < 20) { if (@is_dir($rDir) && $this->recyclerFN != $fI['file']) { return $rDir; } $theFile = $fI['path']; $theFile = \TYPO3\CMS\Core\Utility\PathUtility::getCanonicalPath($theFile); $fI = GeneralUtility::split_fileref($theFile); $c++; } } }
/** * Cleans $theDir for slashes in the end of the string and returns the new path, if it exists on the server. * * @param string Directory path to check * @return string Returns the cleaned up directory name if OK, otherwise FALSE. * @todo Deprecate: but still in use by getUniqueName (used by DataHandler) * @deprecated but still in use in the Core. Don't use in your extensions! */ public function is_directory($theDir) { // @todo: should go into the LocalDriver in a protected way (not important to the outside world) if (GeneralUtility::validPathStr($theDir)) { $theDir = PathUtility::getCanonicalPath($theDir); if (@is_dir($theDir)) { return $theDir; } } return false; }
/** * Bulk function, can be used for anything to get a file or folder * * 1. It's a UID * 2. It's a combined identifier * 3. It's just a path/filename (coming from the oldstyle/backwards compatibility) * * Files, previously laid on fileadmin/ or something, will be "mapped" to the storage the file is * in now. Files like typo3temp/ or typo3conf/ will be moved to the first writable storage * in its processing folder * * $input could be * - "2:myfolder/myfile.jpg" (combined identifier) * - "23" (file UID) * - "uploads/myfile.png" (backwards-compatibility, storage "0") * - "file:23" * * @param string $input * @return FileInterface|Folder */ public function retrieveFileOrFolderObject($input) { // Remove PATH_site because absolute paths under Windows systems contain ':' // This is done in all considered sub functions anyway $input = str_replace(PATH_site, '', $input); if (GeneralUtility::isFirstPartOfStr($input, 'file:')) { $input = substr($input, 5); return $this->retrieveFileOrFolderObject($input); } elseif (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($input)) { return $this->getFileObject($input); } elseif (strpos($input, ':') > 0) { list($prefix, $folderIdentifier) = explode(':', $input); if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($prefix)) { // path or folder in a valid storageUID return $this->getObjectFromCombinedIdentifier($input); } elseif ($prefix == 'EXT') { $input = GeneralUtility::getFileAbsFileName($input); if (empty($input)) { return NULL; } $input = PathUtility::getRelativePath(PATH_site, dirname($input)) . basename($input); return $this->getFileObjectFromCombinedIdentifier($input); } else { return NULL; } } else { // this is a backwards-compatible way to access "0-storage" files or folders // eliminate double slashes, /./ and /../ $input = \TYPO3\CMS\Core\Utility\PathUtility::getCanonicalPath(ltrim($input, '/')); if (@is_file(PATH_site . $input)) { // only the local file return $this->getFileObjectFromCombinedIdentifier($input); } else { // only the local path return $this->getFolderObjectFromCombinedIdentifier($input); } } }
/** * Move an temporary uploaded file to the upload folder * * @return string */ public function moveTempFileToTempFolder() { $result = ''; $fileData = $this->getUploadedFileInfo(); if (count($fileData)) { /** @var $basicFileFunctions \TYPO3\CMS\Core\Utility\File\BasicFileUtility */ $basicFileFunctions = $this->objectManager->get(\TYPO3\CMS\Core\Utility\File\BasicFileUtility::Class); $filename = $basicFileFunctions->cleanFileName($fileData['filename']); $uploadFolder = \TYPO3\CMS\Core\Utility\PathUtility::getCanonicalPath(PATH_site . $this->tempFolder); $this->createUploadFolderIfNotExist($uploadFolder); $uniqueFilename = $basicFileFunctions->getUniqueName($filename, $uploadFolder); if (GeneralUtility::upload_copy_move($fileData['tmp_name'], $uniqueFilename)) { $result = basename($uniqueFilename); } } return $result; }
/** * Makes sure the Path given as parameter is valid * * @param string $filePath The file path (including the file name!) * @return string * @throws \TYPO3\CMS\Core\Resource\Exception\InvalidPathException */ protected function canonicalizeAndCheckFilePath($filePath) { $filePath = PathUtility::getCanonicalPath($filePath); // filePath must be valid // Special case is required by vfsStream in Unit Test context if (!GeneralUtility::validPathStr($filePath)) { throw new \TYPO3\CMS\Core\Resource\Exception\InvalidPathException('File ' . $filePath . ' is not valid (".." and "//" is not allowed in path).', 1320286857); } return $filePath; }
/** * Removes all dots, slashes and spaces after a path * * @param string $theDir Input string * @return string Output string * @deprecated since TYPO3 6.1, will be removed in two versions, use \TYPO3\CMS\Core\Utility\PathUtility::getCanonicalPath() instead */ public function cleanDirectoryName($theDir) { GeneralUtility::logDeprecatedFunction(); return PathUtility::getCanonicalPath($theDir); }
/** * @param ResourceStorage $storage * @return string */ protected function getResourcesSourcePathByResourceStorage(ResourceStorage $storage) { $storageConfiguration = $storage->getConfiguration(); if ($storageConfiguration['pathType'] === 'absolute') { $sourcePath = PathUtility::getCanonicalPath($storageConfiguration['basePath']) . '/'; } else { $sourcePath = PathUtility::getCanonicalPath(PATH_site . $storageConfiguration['basePath']) . '/'; } return $sourcePath; }