/** * Constructor * * @param string $packageKey Key of this package * @param string $packagePath Absolute path to the package's main directory * @param string $classesPath Path the classes of the package are in, relative to $packagePath. Optional, defaults to 'Classes' * @throws \TYPO3\FLOW3\Package\Exception\InvalidPackageKeyException if an invalid package key was passed * @throws \TYPO3\FLOW3\Package\Exception\InvalidPackagePathException if an invalid package path was passed */ public function __construct($packageKey, $packagePath, $classesPath = self::DIRECTORY_CLASSES) { if (preg_match(self::PATTERN_MATCH_PACKAGEKEY, $packageKey) !== 1) { throw new \TYPO3\FLOW3\Package\Exception\InvalidPackageKeyException('"' . $packageKey . '" is not a valid package key.', 1217959510); } if (!(is_dir($packagePath) || \TYPO3\FLOW3\Utility\Files::is_link($packagePath) && is_dir(realpath(rtrim($packagePath, '/'))))) { throw new \TYPO3\FLOW3\Package\Exception\InvalidPackagePathException('Package path does not exist or is no directory.', 1166631889); } if (substr($packagePath, -1, 1) !== '/') { throw new \TYPO3\FLOW3\Package\Exception\InvalidPackagePathException('Package path has no trailing forward slash.', 1166633720); } if (substr($classesPath, 1, 1) === '/') { throw new \TYPO3\FLOW3\Package\Exception\InvalidPackagePathException('Package classes path has a leading forward slash.', 1334841320); } $this->packageKey = $packageKey; $this->packagePath = $packagePath; $this->classesPath = $classesPath; }
/** * Depending on the settings of this publishing target copies the specified file * or creates a symbolic link. * * @param string $sourcePathAndFilename * @param string $targetPathAndFilename * @param boolean $createDirectoriesIfNecessary * @return void * @throws \TYPO3\FLOW3\Resource\Exception */ protected function mirrorFile($sourcePathAndFilename, $targetPathAndFilename, $createDirectoriesIfNecessary = FALSE) { if ($createDirectoriesIfNecessary === TRUE) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively(dirname($targetPathAndFilename)); } switch ($this->settings['resource']['publishing']['fileSystem']['mirrorMode']) { case 'copy': copy($sourcePathAndFilename, $targetPathAndFilename); touch($targetPathAndFilename, filemtime($sourcePathAndFilename)); break; case 'link': if (file_exists($targetPathAndFilename)) { if (\TYPO3\FLOW3\Utility\Files::is_link($targetPathAndFilename) && $this->realpath($targetPathAndFilename) === $this->realpath($sourcePathAndFilename)) { break; } unlink($targetPathAndFilename); symlink($sourcePathAndFilename, $targetPathAndFilename); } else { symlink($sourcePathAndFilename, $targetPathAndFilename); } break; default: throw new \TYPO3\FLOW3\Resource\Exception('An invalid mirror mode (' . $this->settings['resource']['publishing']['fileSystem']['mirrorMode'] . ') has been configured.', 1256133400); } if (!file_exists($targetPathAndFilename)) { throw new \TYPO3\FLOW3\Resource\Exception('The resource "' . $sourcePathAndFilename . '" could not be mirrored.', 1207255453); } }
/** * Returns the publish path and filename to be used to publish the specified persistent resource * * @FLOW3\Around("method(TYPO3\FLOW3\Resource\Publishing\FileSystemPublishingTarget->buildPersistentResourcePublishPathAndFilename()) && setting(TYPO3.FLOW3.security.enable)") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return mixed Result of the target method */ public function rewritePersistentResourcePublishPathAndFilenameForPrivateResources(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $resource = $joinPoint->getMethodArgument('resource'); $configuration = $resource->getPublishingConfiguration(); $returnFilename = $joinPoint->getMethodArgument('returnFilename'); if ($configuration === NULL || $configuration instanceof \TYPO3\FLOW3\Security\Authorization\Resource\SecurityPublishingConfiguration === FALSE) { return $joinPoint->getAdviceChain()->proceed($joinPoint); } $publishingPath = FALSE; $allowedRoles = $configuration->getAllowedRoles(); if (count(array_intersect($allowedRoles, $this->securityContext->getRoles())) > 0) { $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($joinPoint->getProxy()->getResourcesPublishingPath(), 'Persistent/', $this->session->getID())) . '/'; $filename = $resource->getResourcePointer()->getHash() . '.' . $resource->getFileExtension(); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($publishingPath); $this->accessRestrictionPublisher->publishAccessRestrictionsForPath($publishingPath); if ($this->settings['resource']['publishing']['fileSystem']['mirrorMode'] === 'link') { foreach ($allowedRoles as $role) { $roleDirectory = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($this->environment->getPathToTemporaryDirectory(), 'PrivateResourcePublishing/', $role)); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($roleDirectory); if (file_exists($publishingPath . $role)) { if (\TYPO3\FLOW3\Utility\Files::is_link(\TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))) && realpath(\TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))) === $roleDirectory) { continue; } unlink($publishingPath . $role); symlink($roleDirectory, \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))); } else { symlink($roleDirectory, \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))); } } $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $allowedRoles[0])) . '/'; } if ($returnFilename === TRUE) { $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $filename)); } } return $publishingPath; }
/** * @test */ public function is_linkReturnsFalseForStreamWrapperPaths() { $targetPath = 'vfs://Foo/Bar'; if (!is_dir($targetPath)) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($targetPath); } $this->assertFalse(\TYPO3\FLOW3\Utility\Files::is_link($targetPath)); }
/** * Because mirrorFile() uses touch() we can't use vfs to mock the file system. * * @test */ public function mirrorFileSymLinksTheGivenFileIfTheSettingSaysSo() { $sourcePathAndFilename = tempnam('FLOW3FileSystemPublishingTargetTestSource', ''); $targetPathAndFilename = tempnam('FLOW3FileSystemPublishingTargetTestTarget', ''); file_put_contents($sourcePathAndFilename, 'some data'); touch($sourcePathAndFilename, time() - 5); $settings = array('resource' => array('publishing' => array('fileSystem' => array('mirrorMode' => 'link')))); $publishingTarget = $this->getAccessibleMock('TYPO3\\FLOW3\\Resource\\Publishing\\FileSystemPublishingTarget', array('dummy')); $publishingTarget->_set('settings', $settings); $publishingTarget->_call('mirrorFile', $sourcePathAndFilename, $targetPathAndFilename, TRUE); $this->assertFileEquals($sourcePathAndFilename, $targetPathAndFilename); $this->assertTrue(\TYPO3\FLOW3\Utility\Files::is_link($targetPathAndFilename)); unlink($sourcePathAndFilename); unlink($targetPathAndFilename); }